Merge remote-tracking branch 'public/master' into dev_lime

Conflicts:
	build/android/Android.mk
	coreapi/private.h
This commit is contained in:
Guillaume BIENKOWSKI 2014-10-31 10:47:13 +01:00
commit dec0ccb9df
60 changed files with 2538 additions and 572 deletions

3
.gitignore vendored
View file

@ -73,3 +73,6 @@ tools/xml2lpc_test
coreapi/help/filetransfer
tester/receive_file.dump
tester/tmp.db
.DS_Store
Linphone.app
*.dmg

View file

@ -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)

31
README
View file

@ -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.

View file

@ -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:
<binary >
${prefix:ms2plugins}/lib/mediastreamer/plugins/*.*.so
</binary>
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

184
README.macos.md Normal file
View file

@ -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:
<binary>
${prefix:ms2plugins}/lib/mediastreamer/plugins/*.*.so
</binary>
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`.

View file

@ -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

View file

@ -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)

View file

@ -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) \

View file

@ -53,8 +53,8 @@
<ItemDefinitionGroup>
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\belle-sip\include;$(ProjectDir)..\..\oRTP\include;$(ProjectDir)..\..\mediastreamer2\include;$(ProjectDIr)..\..\..\tunnel\include;$(ProjectDir)..\..\coreapi;$(ProjectDir)..\..\include;$(SolutionDir)$(Platform)\$(Configuration)\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>__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)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(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)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>__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)</PreprocessorDefinitions>
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<CompileAsWinRT>false</CompileAsWinRT>
@ -74,7 +74,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
<ClCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_DEBUG;MSG_STORAGE_ENABLED;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -82,7 +82,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
<ClCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>NDEBUG;MSG_STORAGE_ENABLED;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Optimization>MaxSpeed</Optimization>
<StringPooling>true</StringPooling>
<FunctionLevelLinking>true</FunctionLevelLinking>
@ -121,6 +121,7 @@
<ClCompile Include="..\..\coreapi\linphonecore.c" />
<ClCompile Include="..\..\coreapi\linphone_tunnel.cc" />
<ClCompile Include="..\..\coreapi\linphone_tunnel_config.c" />
<ClCompile Include="..\..\coreapi\localplayer.c" />
<ClCompile Include="..\..\coreapi\lpconfig.c" />
<ClCompile Include="..\..\coreapi\lsd.c" />
<ClCompile Include="..\..\coreapi\message_storage.c" />
@ -189,6 +190,9 @@
<ProjectReference Include="..\..\..\mswp8vid\mswp8vid\mswp8vid.vcxproj">
<Project>{0565952a-ea62-46a2-8261-f5b4b490da42}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\sqlite\sqlite.vcxproj">
<Project>{a45d63b9-60de-476c-8836-f8eedbe139d0}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\tunnel\build\wp8\tunnel\tunnel.vcxproj">
<Project>{59500dd1-b192-4ddf-a402-8a8e3739e032}</Project>
</ProjectReference>
@ -201,6 +205,9 @@
<ProjectReference Include="libxml2\libxml2.vcxproj">
<Project>{5dfa07b4-0be9-46a9-ba32-fdf5a55c580b}</Project>
</ProjectReference>
<ProjectReference Include="zlib\zlib.vcxproj">
<Project>{7afac3bb-d97b-4578-b9fe-5e1d2b94ea2f}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsPhone\v$(TargetPlatformVersion)\Microsoft.Cpp.WindowsPhone.$(TargetPlatformVersion).targets" />

513
build/wp8/zlib/zconf.h Normal file
View file

@ -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 <windows.h>
/* 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 <limits.h>
# 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 <sys/types.h> /* for off_t */
# endif
#endif
#if defined(STDC) || defined(Z_HAVE_STDARG_H)
# ifndef Z_SOLO
# include <stdarg.h> /* for va_list */
# endif
#endif
#ifdef _WIN32
# ifndef Z_SOLO
# include <stddef.h> /* 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 <unistd.h> /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
# ifdef VMS
# include <unixio.h> /* 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 */

26
build/wp8/zlib/zlib.sln Normal file
View file

@ -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

135
build/wp8/zlib/zlib.vcxproj Normal file
View file

@ -0,0 +1,135 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|ARM">
<Configuration>Debug</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM">
<Configuration>Release</Configuration>
<Platform>ARM</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{7afac3bb-d97b-4578-b9fe-5e1d2b94ea2f}</ProjectGuid>
<RootNamespace>zlib</RootNamespace>
<DefaultLanguage>en-US</DefaultLanguage>
<MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v110_wp80</PlatformToolset>
<IgnoreImportLibrary>false</IgnoreImportLibrary>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<PlatformToolset>v110_wp80</PlatformToolset>
<IgnoreImportLibrary>false</IgnoreImportLibrary>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)$(Platform)\$(Configuration)\$(TargetName)\</IntDir>
</PropertyGroup>
<PropertyGroup>
<GenerateManifest>false</GenerateManifest>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<AdditionalIncludeDirectories>$(ProjectDir);$(ProjectDir)..\..\..\..\zlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_WIN32;_WINDLL;_USRDLL;_CRT_SECURE_NO_WARNINGS;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<CompileAsWinRT>false</CompileAsWinRT>
<AdditionalUsingDirectories>$(WindowsSDK_MetadataPath);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
<ImportLibrary>$(TargetDir)$(TargetName).lib</ImportLibrary>
<AdditionalDependencies>Ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>$(ProjectDir)..\..\..\..\zlib\win32\zlib.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
<ClCompile>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
<ClCompile>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<Optimization>MaxSpeed</Optimization>
<StringPooling>true</StringPooling>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
</ClCompile>
<Link>
<GenerateDebugInformation>false</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<Reference Include="Windows">
<IsWinMDFile>true</IsWinMDFile>
</Reference>
<Reference Include="platform.winmd">
<IsWinMDFile>true</IsWinMDFile>
<Private>false</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\..\zlib\crc32.h" />
<ClInclude Include="..\..\..\..\zlib\deflate.h" />
<ClInclude Include="..\..\..\..\zlib\gzguts.h" />
<ClInclude Include="..\..\..\..\zlib\inffast.h" />
<ClInclude Include="..\..\..\..\zlib\inffixed.h" />
<ClInclude Include="..\..\..\..\zlib\inflate.h" />
<ClInclude Include="..\..\..\..\zlib\inftrees.h" />
<ClInclude Include="..\..\..\..\zlib\trees.h" />
<ClInclude Include="..\..\..\..\zlib\zlib.h" />
<ClInclude Include="..\..\..\..\zlib\zutil.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\..\zlib\adler32.c" />
<ClCompile Include="..\..\..\..\zlib\compress.c" />
<ClCompile Include="..\..\..\..\zlib\crc32.c" />
<ClCompile Include="..\..\..\..\zlib\deflate.c" />
<ClCompile Include="..\..\..\..\zlib\gzclose.c" />
<ClCompile Include="..\..\..\..\zlib\gzlib.c" />
<ClCompile Include="..\..\..\..\zlib\gzread.c" />
<ClCompile Include="..\..\..\..\zlib\gzwrite.c" />
<ClCompile Include="..\..\..\..\zlib\infback.c" />
<ClCompile Include="..\..\..\..\zlib\inffast.c" />
<ClCompile Include="..\..\..\..\zlib\inflate.c" />
<ClCompile Include="..\..\..\..\zlib\inftrees.c" />
<ClCompile Include="..\..\..\..\zlib\trees.c" />
<ClCompile Include="..\..\..\..\zlib\uncompr.c" />
<ClCompile Include="..\..\..\..\zlib\zutil.c" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\..\..\..\zlib\win32\zlib1.rc" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsPhone\v$(TargetPlatformVersion)\Microsoft.Cpp.WindowsPhone.$(TargetPlatformVersion).targets" />
</Project>

View file

@ -63,7 +63,7 @@ liblinphone_la_SOURCES=\
call_log.c \
call_params.c \
player.c \
fileplayer.c \
localplayer.c \
$(GITVERSION_FILE)
if BUILD_UPNP

View file

@ -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<ServerAddr>::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<ServerAddr>::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) {

View file

@ -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;

View file

@ -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))) {

View file

@ -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;
}

View file

@ -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.
**/

View file

@ -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;
}

View file

@ -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

View file

@ -1,65 +0,0 @@
#include "private.h"
#include <mediastreamer2/fileplayer.h>
#include <mediastreamer2/mssndcard.h>
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);
}

View file

@ -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);
}

View file

@ -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;

View file

@ -24,6 +24,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "quality_reporting.h"
#include <math.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <ortp/telephonyevents.h>
#include <ortp/zrtp.h>
#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 <fcntl.h>
#include <io.h>
#define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
#else
#define SET_BINARY_MODE(file)
#endif
#include <zlib.h>
#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);

View file

@ -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, /**<The call's parameters change is requested by remote end, used for example when video is added by remote */
LinphoneCallIncomingEarlyMedia, /**<We are proposing early media to an incoming call */
LinphoneCallUpdating, /**<A call update has been initiated by us */
LinphoneCallReleased /**< The call object is no more retained by the core */
LinphoneCallReleased, /**< The call object is no more retained by the core */
LinphoneCallEarlyUpdatedByRemote, /*<The call is updated by remote while not yet answered (early dialog SIP UPDATE received).*/
LinphoneCallEarlyUpdating /*<We are updating the call while not yet answered (early dialog SIP UPDATE sent)*/
} LinphoneCallState;
LINPHONE_PUBLIC const char *linphone_call_state_to_string(LinphoneCallState cs);
@ -1301,9 +1301,10 @@ typedef struct _LinphoneChatRoom LinphoneChatRoom;
typedef enum _LinphoneChatMessageState {
LinphoneChatMessageStateIdle, /**< Initial state */
LinphoneChatMessageStateInProgress, /**< Delivery in progress */
LinphoneChatMessageStateDelivered, /**< Message succesffully delivered an acknoleged by remote end point */
LinphoneChatMessageStateDelivered, /**< Message successfully delivered and acknowledged by remote end point */
LinphoneChatMessageStateNotDelivered, /**< Message was not delivered */
LinphoneChatMessageStateFileTransferError /**< Message was received(and acknowledged) but cannot get file from server */
LinphoneChatMessageStateFileTransferError, /**< Message was received(and acknowledged) but cannot get file from server */
LinphoneChatMessageStateFileTransferDone /**< File transfer has been completed successfully. */
} LinphoneChatMessageState;
/**
@ -1424,7 +1425,7 @@ LINPHONE_PUBLIC const LinphoneAddress* linphone_chat_message_get_to_address(cons
LINPHONE_PUBLIC const char* linphone_chat_message_get_external_body_url(const LinphoneChatMessage* message);
LINPHONE_PUBLIC void linphone_chat_message_set_external_body_url(LinphoneChatMessage* message,const char* url);
LINPHONE_PUBLIC const LinphoneContent* linphone_chat_message_get_file_transfer_information(const LinphoneChatMessage* message);
LINPHONE_PUBLIC void linphone_chat_message_start_file_download(LinphoneChatMessage* message, LinphoneChatMessageStateChangedCb status_cb);
LINPHONE_PUBLIC void linphone_chat_message_start_file_download(LinphoneChatMessage* message, LinphoneChatMessageStateChangedCb status_cb, void* ud);
LINPHONE_PUBLIC void linphone_chat_room_cancel_file_transfer(LinphoneChatMessage* msg);
LINPHONE_PUBLIC const char* linphone_chat_message_get_appdata(const LinphoneChatMessage* message);
LINPHONE_PUBLIC void linphone_chat_message_set_appdata(LinphoneChatMessage* message, const char* data);
@ -1442,6 +1443,8 @@ LINPHONE_PUBLIC bool_t linphone_chat_message_is_outgoing(LinphoneChatMessage* me
LINPHONE_PUBLIC unsigned int linphone_chat_message_get_storage_id(LinphoneChatMessage* message);
LINPHONE_PUBLIC LinphoneReason linphone_chat_message_get_reason(LinphoneChatMessage* msg);
LINPHONE_PUBLIC const LinphoneErrorInfo *linphone_chat_message_get_error_info(const LinphoneChatMessage *msg);
LINPHONE_PUBLIC void linphone_chat_message_set_file_transfer_filepath(LinphoneChatMessage *msg, const char *filepath);
LINPHONE_PUBLIC const char * linphone_chat_message_get_file_transfer_filepath(LinphoneChatMessage *msg);
/**
* @}
*/
@ -1466,6 +1469,14 @@ typedef enum _LinphoneGlobalState{
const char *linphone_global_state_to_string(LinphoneGlobalState gs);
/**
* LinphoneCoreLogCollectionUploadState is used to notify if log collection upload have been succesfully delivered or not.
*/
typedef enum _LinphoneCoreLogCollectionUploadState {
LinphoneCoreLogCollectionUploadStateInProgress, /**< Delivery in progress */
LinphoneCoreLogCollectionUploadStateDelivered, /**< Log collection upload successfully delivered and acknowledged by remote end point */
LinphoneCoreLogCollectionUploadStateNotDelivered, /**< Log collection upload was not delivered */
} LinphoneCoreLogCollectionUploadState;
/**
* Global state notification callback.
@ -1599,10 +1610,10 @@ typedef void (*LinphoneCoreFileTransferSendCb)(LinphoneCore *lc, LinphoneChatMes
* @param lc #LinphoneCore object
* @param message #LinphoneChatMessage message from which the body is received.
* @param content #LinphoneContent incoming content information
* @param progress number of bytes sent/received from the begening of the transfer.
*
* @param offset The number of bytes sent/received since the beginning of the transfer.
* @param total The total number of bytes to be sent/received.
*/
typedef void (*LinphoneCoreFileTransferProgressIndicationCb)(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, size_t progress);
typedef void (*LinphoneCoreFileTransferProgressIndicationCb)(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, size_t offset, size_t total);
/**
* Is composing notification callback prototype.
@ -1672,6 +1683,21 @@ typedef void (*LinphoneCoreConfiguringStatusCb)(LinphoneCore *lc, LinphoneConfig
*/
typedef void (*LinphoneCoreNetworkReachableCb)(LinphoneCore *lc, bool_t reachable);
/**
* Callback prototype for reporting log collection upload state change.
* @param[in] lc LinphoneCore object
* @param[in] state The state of the log collection upload
* @param[in] info Additional information: error message in case of error state, URL of uploaded file in case of success.
*/
typedef void (*LinphoneCoreLogCollectionUploadStateChangedCb)(LinphoneCore *lc, LinphoneCoreLogCollectionUploadState state, const char *info);
/**
* Callback prototype for reporting log collection upload progress indication.
* @param[in] lc LinphoneCore object
* @param[in] progress Percentage of the file size of the log collection already uploaded.
*/
typedef void (*LinphoneCoreLogCollectionUploadProgressIndicationCb)(LinphoneCore *lc, size_t progress);
/**
* This structure holds all callbacks that the application should implement.
* None is mandatory.
@ -1702,24 +1728,26 @@ typedef struct _LinphoneCoreVTable{
DisplayMessageCb display_warning;/**< @deprecated Callback to display a warning to the user */
DisplayUrlCb display_url; /**< @deprecated */
ShowInterfaceCb show; /**< @deprecated Notifies the application that it should show up*/
LinphoneCoreTextMessageReceivedCb text_received; /** @deprecated, use #message_received instead <br> A text message has been received */
LinphoneCoreFileTransferRecvCb file_transfer_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 <br> 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

View file

@ -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 <belle-sip/wakelock.h>
#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;
}
}

98
coreapi/localplayer.c Normal file
View file

@ -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 <mediastreamer2/msmediaplayer.h>
#include <mediastreamer2/mssndcard.h>
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);
}

View file

@ -49,7 +49,9 @@
#include <libgen.h>
#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;
}

View file

@ -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));
}
}

View file

@ -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);

View file

@ -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){

View file

@ -125,12 +125,13 @@ struct _LinphoneCallLog{
LinphoneAddress *from; /**<Originator of the call as a LinphoneAddress object*/
LinphoneAddress *to; /**<Destination of the call as a LinphoneAddress object*/
char start_date[128]; /**<Human readable string containing the start date*/
int duration; /**<Duration of the call in seconds*/
int duration; /**<Duration of the call starting in connected state in seconds*/
char *refkey;
rtp_stats_t local_stats;
rtp_stats_t remote_stats;
float quality;
time_t start_date_time; /**Start date of the call in seconds as expressed in a time_t */
time_t connected_date_time; /**Connecting date of the call in seconds as expressed in a time_t */
char* call_id; /**unique id of a call*/
struct _LinphoneQualityReporting reporting;
bool_t video_enabled;
@ -171,6 +172,7 @@ struct _LinphoneChatMessage {
LinphoneContent *file_transfer_information; /**< used to store file transfer information when the message is of file transfer type */
char *content_type; /**< is used to specified the type of message to be sent, used only for file transfer message */
belle_http_request_t *http_request; /**< keep a reference to the http_request in case of file transfer in order to be able to cancel the transfer */
char *file_transfer_filepath;
};
BELLE_SIP_DECLARE_VPTR(LinphoneChatMessage);
@ -203,7 +205,6 @@ struct _LinphoneCall
SalOp *op;
SalOp *ping_op;
char localip[LINPHONE_IPADDR_SIZE]; /* our best guess for local ipaddress for this call */
time_t media_start_time; /*time at which it was accepted, media streams established*/
LinphoneCallState state;
LinphoneCallState prevstate;
LinphoneCallState transfer_state; /*idle if no transfer*/
@ -769,6 +770,7 @@ struct _LinphoneCore
bool_t lime;
char *file_transfer_server;
const char **supported_formats;
LinphoneContent *log_collection_upload_information;
};
@ -921,12 +923,17 @@ struct _LinphonePlayer{
int (*pause)(struct _LinphonePlayer* player);
int (*seek)(struct _LinphonePlayer* player, int time_ms);
MSPlayerState (*get_state)(struct _LinphonePlayer* player);
int (*get_duration)(struct _LinphonePlayer *player);
int (*get_position)(struct _LinphonePlayer *player);
void (*close)(struct _LinphonePlayer* player);
void (*destroy)(struct _LinphonePlayer *player);
LinphonePlayerEofCallback cb;
void *user_data;
void *impl;
};
void _linphone_player_destroy(LinphonePlayer *player);
/*****************************************************************************
* XML UTILITY FUNCTIONS *
@ -1003,7 +1010,7 @@ void linphone_core_notify_text_message_received(LinphoneCore *lc, LinphoneChatRo
void linphone_core_notify_message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *message);
void linphone_core_notify_file_transfer_recv(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, const char* buff, size_t size);
void linphone_core_notify_file_transfer_send(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, char* buff, size_t* size);
void linphone_core_notify_file_transfer_progress_indication(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, size_t progress);
void linphone_core_notify_file_transfer_progress_indication(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, size_t offset, size_t total);
void linphone_core_notify_is_composing_received(LinphoneCore *lc, LinphoneChatRoom *room);
void linphone_core_notify_dtmf_received(LinphoneCore* lc, LinphoneCall *call, int dtmf);
/*
@ -1020,6 +1027,8 @@ void linphone_core_notify_network_reachable(LinphoneCore *lc, bool_t reachable);
void linphone_core_notify_notify_received(LinphoneCore *lc, LinphoneEvent *lev, const char *notified_event, const LinphoneContent *body);
void linphone_core_notify_subscription_state_changed(LinphoneCore *lc, LinphoneEvent *lev, LinphoneSubscriptionState state);
void linphone_core_notify_publish_state_changed(LinphoneCore *lc, LinphoneEvent *lev, LinphonePublishState state);
void linphone_core_notify_log_collection_upload_state_changed(LinphoneCore *lc, LinphoneCoreLogCollectionUploadState state, const char *info);
void linphone_core_notify_log_collection_upload_progress_indication(LinphoneCore *lc, size_t progress);
void set_mic_gain_db(AudioStream *st, float gain);
void set_playback_gain_db(AudioStream *st, float gain);

View file

@ -881,8 +881,11 @@ static bool_t is_a_phone_number(const char *username){
*p==')' ||
*p=='(' ||
*p=='/' ||
*p=='+') continue;
else return FALSE;
*p=='+' ||
(unsigned char)*p== 0xca // non-breakable space (iOS uses it to format contacts phone number)
)
continue;
return FALSE;
}
return TRUE;
}

View file

@ -379,7 +379,7 @@ GtkWidget* linphone_gtk_init_chatroom(LinphoneChatRoom *cr, const LinphoneAddres
GdkColor colorb;
int idx;
GtkWidget *button;
GtkWidget *entry;
GtkWidget *entry = linphone_gtk_get_widget(chat_view,"text_entry");
MSList *messages;
GHashTable *table;
char *with_str;
@ -423,7 +423,7 @@ GtkWidget* linphone_gtk_init_chatroom(LinphoneChatRoom *cr, const LinphoneAddres
display_history_message(chat_view,messages,with);
button = linphone_gtk_get_widget(chat_view,"send");
g_signal_connect_swapped(G_OBJECT(button),"clicked",(GCallback)linphone_gtk_send_text,NULL);
entry = linphone_gtk_get_widget(chat_view,"text_entry");
g_signal_connect_swapped(G_OBJECT(entry),"activate",(GCallback)linphone_gtk_send_text,NULL);
g_signal_connect_swapped(G_OBJECT(entry),"changed",(GCallback)linphone_gtk_compose_text,NULL);
g_signal_connect(G_OBJECT(notebook),"switch_page",(GCallback)linphone_gtk_notebook_tab_select,NULL);

View file

@ -440,9 +440,9 @@ GtkWidget *linphone_gtk_create_widget(const char *filename, const char *widget_n
return w;
}
static void entry_unmapped(GtkWidget *entry){
g_message("Entry is unmapped, calling unrealize to workaround chinese bug.");
gtk_widget_unrealize(entry);
static void entry_unmapped(GtkWidget *widget){
ms_message("%s is unmapped, calling unrealize to workaround chinese bug.",G_OBJECT_TYPE_NAME(widget));
gtk_widget_unrealize(widget);
}
GtkWidget *linphone_gtk_get_widget(GtkWidget *window, const char *name){
@ -459,10 +459,10 @@ GtkWidget *linphone_gtk_get_widget(GtkWidget *window, const char *name){
g_error("No widget named %s found in xml interface.",name);
}
if (workaround_gtk_entry_chinese_bug){
if (strcmp(G_OBJECT_TYPE_NAME(w),"GtkEntry")==0){
if (strcmp(G_OBJECT_TYPE_NAME(w),"GtkEntry")==0 || strcmp(G_OBJECT_TYPE_NAME(w),"GtkTextView")==0){
if (g_object_get_data(G_OBJECT(w),"entry_bug_workaround")==NULL){
g_object_set_data(G_OBJECT(w),"entry_bug_workaround",GINT_TO_POINTER(1));
g_message("%s is a GtkEntry",name);
ms_message("%s is a %s",name,G_OBJECT_TYPE_NAME(w));
g_signal_connect(G_OBJECT(w),"unmap",(GCallback)entry_unmapped,NULL);
}
}

View file

@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "linphone.h"
#ifdef __linux
#ifdef GDK_WINDOWING_X11
#include <gdk/gdkx.h>
#elif defined(WIN32)
#include <gdk/gdkwin32.h>
@ -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);

Binary file not shown.

Binary file not shown.

View file

@ -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();
}

View file

@ -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);
}

View file

@ -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();
}

View file

@ -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));
}
}

View file

@ -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;
}
}
}

View file

@ -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);
}
}

@ -1 +1 @@
Subproject commit 91f2782073c776b2d5ce3ab0a12561aea7610068
Subproject commit 9dd1d9633e66ea018d346cc79a6d93ff6daeddf1

2
oRTP

@ -1 +1 @@
Subproject commit 540ee49bd3f65139f7e5938cc6bc1f8a4353c3f7
Subproject commit 90a19604d061d7f23189feb925847e66d366898e

View file

@ -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\" <sip:pauline@super.net>";
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\" <tel:+12345>");*/
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 = {

View file

@ -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);

View file

@ -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 */

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
#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[] = {

View file

@ -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 = {

View file

@ -38,4 +38,7 @@ automatically_accept=0
device=StaticImage: Static picture
[sound]
echocancellation=0 #to not overload cpu in case of VG
echocancellation=0 #to not overload cpu in case of VG
[net]
dns_srv_enabled=0 #no srv needed in general

View file

@ -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

View file

@ -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

View file

@ -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];

Binary file not shown.

View file

@ -52,7 +52,7 @@ void CplusplusGenerator::generate(Project *proj){
void CplusplusGenerator::writeEnumMember(ConstField *cf, bool isLast){
writeTabs(1);
mOutfile<<cf->getName();
mOutfile<<cf->getName()<<"="<<cf->getValue();
if (!isLast) mOutfile<<",";
if (!cf->getHelp().empty()) mOutfile<<"\t/**< "<<cf->getHelp()<<" */";
mOutfile<<endl;
@ -222,7 +222,6 @@ void JavascriptGenerator::writeEnum(Class *klass){
list<ConstField*> members=klass->getConstFields();
list<ConstField*>::iterator it;
string enum_name=getEnumName(klass);
int value=0;
filename<<to_lower(mCurProj->getName())<<"/"<<to_lower(enum_name)<<".js";
mOutfile.open(filename.str().c_str());
@ -243,7 +242,7 @@ void JavascriptGenerator::writeEnum(Class *klass){
string prefix=ConstField::getCommonPrefix(members);
size_t prefix_size=prefix.size();
for(it=members.begin();it!=members.end();value++){
for(it=members.begin();it!=members.end();){
ConstField *cf=(*it);
if (!cf->getHelp().empty()){
writeTabs(1);
@ -254,7 +253,7 @@ void JavascriptGenerator::writeEnum(Class *klass){
mOutfile<<"*/"<<endl;
}
writeTabs(1);
mOutfile<<cf->getName().substr(prefix_size,string::npos)<<" : "<<value;
mOutfile<<cf->getName().substr(prefix_size,string::npos)<<" : "<<cf->getValue();
if (++it!=members.end()) mOutfile<<",";
mOutfile<<endl;
}

View file

@ -335,11 +335,26 @@ static void parseEnum(Project *proj, XmlNode node){
klass->setHelp(node.getChild("detaileddescription").getChild("para").getText());
list<XmlNode> enumValues=node.getChildren("enumvalue");
list<XmlNode>::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++;
}
}

View file

@ -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

View file

@ -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<ConstField *> fields){
@ -338,7 +338,7 @@ public:
private:
Type *mType;
string mName;
string mValue;
int mValue;
string mHelp;
};