Merge branch 'master' of git.linphone.org:linphone

Conflicts:
	configure.ac
This commit is contained in:
Guillaume Beraudo 2013-06-25 12:42:43 +02:00
commit c991f420ec
137 changed files with 22130 additions and 16739 deletions

View file

@ -48,17 +48,17 @@ ISCC=ISCC.exe
PACKAGE_WIN32_FILELIST=$(PACKAGE)-win32.filelist
PACKAGE_BUNDLE_FILE=$(top_srcdir)/build/macos/$(PACKAGE).bundle
EXTRA_DIST = config.rpath BUGS linphone.kdevelop \
README.arm \
README.mingw \
README.macos \
autogen.sh \
linphone.spec \
linphone.spec.in \
$(GTK_FILELIST) \
gen-gtkfilelist.sh \
$(LINPHONEDEPS_FILELIST) \
$(ISS_SCRIPT).in
EXTRA_DIST = BUGS \
README.arm \
README.mingw \
README.macos \
autogen.sh \
linphone.spec \
linphone.spec.in \
$(GTK_FILELIST) \
gen-gtkfilelist.sh \
$(LINPHONEDEPS_FILELIST) \
$(ISS_SCRIPT).in
DISTCLEANFILES= $(ISS_SCRIPT) $(PACKAGE_WIN32_FILELIST)
@ -220,7 +220,7 @@ bundle: $(LIBICONV_HACK)
printf "[Pango]\nModuleFiles=./etc/pango/pango.modules\n" \
> $(BUNDLEDIR)/Contents/Resources/etc/pango/pangorc
cp -f $(BUNDLEDIR)/Contents/Resources/etc/pango/pango.modules $(BUNDLEDIR)/Contents/Resources/etc/pango/pango.modules.orig
sed -e 's:@executable_path/../Resources:../..:g' $(BUNDLEDIR)/Contents/Resources/etc/pango/pango.modules.orig > $(BUNDLEDIR)/Contents/Resources/etc/pango/pango.modules
sed -e 's:@executable_path.*/::g' $(BUNDLEDIR)/Contents/Resources/etc/pango/pango.modules.orig > $(BUNDLEDIR)/Contents/Resources/etc/pango/pango.modules
cp -f $(LIBICONV_HACK) $(BUNDLEDIR)/Contents/Resources/lib/.
cd $(BUNDLEDIR)/.. && rm -f $(MACAPPZIP) && zip -r $(MACAPPZIP) $(MACAPPNAME) && cd -

27
NEWS
View file

@ -1,6 +1,29 @@
linphone-3.xxx --
linphone-3.6.1 -- June 17, 2013
* fix memory leak with some video cameras on windows.
Requires: mediastreamer2 = 2.9.1 and ortp = 0.22.0
linphone-3.6.0 -- May 27, 2013
UI:
* new friend list and chat messaging UI
* enhanced call history
* call and conference audio recording
* persistent chat history
* DSCP settings for SIP and RTP
* display of call statistics (when clicking on the quality indicator bar)
core:
* ICE for efficient RTP exchange
* fix bug in zRTP support (upgrade required)
*
* call recording
* uPnP
* call statistics
* adaptive bitrate control improvements
* faster call quality indicator feedback
* DSCP settings for SIP and RTP
* detailed call statistics feedback API
Requires: mediastreamer2 = 2.9.0 and ortp = 0.22.0
linphone-3.5.2 -- February 22, 2012
* updated oRTP to 0.20.0

59
README
View file

@ -2,21 +2,62 @@ This is Linphone, a free (GPL) video softphone based on the SIP protocol.
******************Building linphone ***********************************
- Install build time dependencies
- libtool
- intltool
- you need at least:
- libosip2>=3.0.3
- libeXosip2>=3.0.3
- speex>=1.2.0 (including libspeexdsp part)
- libreadline (optional: for convenient command line in linphonec)
+ gsm codec (gsm source package or libgsm-dev or gsm-devel) (optional)
+ if you want to gtk/glade interface:
- gtk>=2.16.0
- libosip2>=3.5.0
- libeXosip2>=3.5.0
- speex>=1.2.0 (including libspeexdsp part)
+ if you want the gtk/glade interface:
- libgtk >=2.16.0
+ if you want video support:
- SDL>=1.2.10
- libvpx (VP8 codec)
- libavcodec (ffmpeg)
- libswscale (part of ffmpeg too) for better scaling performance
- libxv (x11 video extension)
- ligl1-mesa (OpenGL API -- GLX development files)
- libglew (OpenGL Extension Wrangler library)
- libv4l (Video for linux)
- libx11 (x11)
- theora (optional)
+ gsm codec (gsm source package or libgsm-dev or gsm-devel) (optional)
+ libreadline (optional: for convenient command line in linphonec)
+ libsoup (optional: for wizard - account creation assistant)
+ libsqlite3 (optional : for a local history of chat messages)
+ 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
$ sudo apt-get install libtool intltool libgtk2.0-dev libosip2-dev libexosip2-dev libspeexdsp-dev libavcodec-dev libswscale-dev libx11-dev libvx-dev ligl1-mesa-dev libglew-dev libv4l-dev
+ for optional library
$ sudo apt-get install libreadline-dev liggsm1-dev libtheora-dev libsoup2.4-dev libsqlit3-dev libupnp6-dev
+ Install srtp (optional) for call encryption :
$ git clone git://git.linphone.org/srtp.git
$ cd srtp && autoconf && ./configure && make
$ sudo make install
+ Install zrtpcpp (optional), for unbreakable call encryption
$ sudo apt-get install cmake libssl-dev
$ git clone git://git.linphone.org/zrtpcpp.git
$ cd zrtpcpp && cmake -Denable-ccrtp=false . && make
$ sudo make install
- Compile linphone
$ ./autogen.sh
$ ./configure
$ make && sudo make install
$ sudo ldconfig
with their corresponding -dev or -devel package if you don't use source packages.
For windows compilation see README.mingw.
For macOS X, see README.macos

View file

@ -7,57 +7,78 @@ You need:
- 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 it is recommended to edit /opt/local/etc/macports/macports.conf to add the
following line:
macosx_deployment_target 10.6
- Install build time dependencies
$ port install automake autoconf libtool intltool
$ sudo port install automake autoconf libtool intltool
- Install some linphone dependencies with macports
$ port install speex
$ port install libosip2 # WARNING: currently outdated in macport
$ port install libeXosip2 #WARNING: currently outdated in macport
$ port install ffmpeg-devel
$ port install libvpx
$ port install readline
$ sudo port install speex
$ sudo port install libosip2 # WARNING: currently outdated in macport
$ sudo port install libeXosip2 #WARNING: currently outdated in macport
$ sudo port install ffmpeg-devel -gpl2
$ sudo port install libvpx
$ sudo port install readline
- 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
- Install additional librairies required for wizard (linphone.org account creation assistant)
$ sudo port install libsoup
- Install sqlite3 for message storage
$ sudo port install sqlite3
The softwares below need to be compiled manually. To ensure compatibility with multiple mac os version it is recommended to do:
$ export MACOSX_DEPLOYMENT_TARGET=10.6
- Install srtp (optional) for call encryption
$ port install srtp
$ sudo port install srtp
If that fails, get from source:
$ 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
$ port install cmake
$ sudo port install cmake
$ git clone git://git.linphone.org/zrtpcpp.git
$ cd zrtpcpp && cmake -Denable-ccrtp=false . && make
$ sudo make install
- Install gtk. It is recommended to use the quartz backend for better integration.
$ port install gtk2 +quartz +no_x11
$ port install ige-mac-integration
$ port install hicolor-icon-theme
** WARNING 2013-03-06 glib-networking is currently broken in macports - generates crashes or hangs when used in a bundle **
As a temporary workaround, build a newer version by yourself:
$ wget http://ftp.gnome.org/pub/gnome/sources/glib-networking/2.34/glib-networking-2.34.2.tar.xz
$ tar -xvzf glib-networking-2.34.2.tar.xz
$ cd glib-networking-2.34.2
$ ./configure --prefix=/opt/local --without-ca-certificates && make
$ sudo make install
- Compile and install the tunnel
- Compile and install the tunnel library (optional, proprietary extension only)
If you got the source code from git, run ./autogen.sh first
If you got the source code from git, run ./autogen.sh first
Then or otherwise, do:
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.
If you got the source code from git, run ./autogen.sh first.
Then or otherwise, do:
Then or otherwise, do:
$ ./configure --prefix=/opt/local --with-readline=/opt/local --disable-x11 --with-srtp=/opt/local --with-gsm=/opt/local --enable-zrtp && make
Install to /opt/local
Install to /opt/local
$ sudo make install
Done.
Done.
If you want to generate a portable bundle, then install gtk-mac-bundler.
Use git:
@ -68,8 +89,7 @@ Use git:
$ sudo touch touch /opt/local/lib/charset.alias
Then run, inside linphone source tree:
1. Run configure as told before but with "--enable-relativeprefix" appended.
Run configure as told before but with "--enable-relativeprefix" appended.
$ make
$ make bundle
@ -85,4 +105,20 @@ For a better appearance, you can install the gtk-quartz-engine (a gtk theme) tha
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

@ -136,11 +136,21 @@ libgnutls (from the web)
libgsm (from the web)
libxml2 (compiled)
libsoup (compiled)
libsqlite3 (compiled)
Remarks:
For every package compiled that goes into linphone-deps, .la files (libtool files) must be removed to avoid libtool errors.
When running "make install DESTDIR=<somepath>", somepath must be absolute and should not contain any ~ or space.
- building sqlite3
* download the sources on the following website:
http://www.sqlite.org/download.html (choose the sqlite-autoconf-3XXX.tar.gz)
* install:
./configure
make && make install DESTDIR=/home/<myuser>/sqlite3-install
then copy the content of ~/sqlite3-install/usr/local/ into linphone-deps/.
- building ffmpeg
./configure --enable-shared --disable-static --enable-memalign-hack --extra-cflags="-fno-common" --enable-gpl && make
make install DESTDIR=/home/<myuser>/ffmpeg-install
@ -152,6 +162,7 @@ When running "make install DESTDIR=<somepath>", somepath must be absolute and sh
./configure --enable-shared --disable-static && make && make install DESTDIR=/home/<myuser>/libxml2-install
copy ~/libxml2-install/usr/local/* into linphone-deps/.
- building x264:
* download yasm normal version windows executable from yasm project page:

View file

@ -21,7 +21,6 @@
LOCAL_PATH:= $(call my-dir)/../../coreapi
include $(CLEAR_VARS)
include $(linphone-root-dir)/submodules/linphone/build/android/common.mk
@ -36,11 +35,16 @@ endif
LOCAL_MODULE := liblinphonenoneon
ifeq ($(TARGET_ARCH_ABI),armeabi)
LOCAL_MODULE_FILENAME := liblinphonearmv5
LOCAL_MODULE_FILENAME := liblinphonearmv5noneon
endif
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
LOCAL_MODULE_FILENAME := liblinphonearmv7noneon
endif
ifeq ($(TARGET_ARCH_ABI),x86)
LOCAL_MODULE_FILENAME := liblinphonex86
endif
include $(BUILD_SHARED_LIBRARY)
$(call import-module,android/cpufeatures)

View file

@ -21,7 +21,6 @@
LOCAL_PATH:= $(call my-dir)/../../coreapi
include $(CLEAR_VARS)
include $(linphone-root-dir)/submodules/linphone/build/android/common.mk
@ -35,7 +34,11 @@ LOCAL_SHARED_LIBRARIES += \
endif
LOCAL_MODULE := liblinphone
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
LOCAL_MODULE_FILENAME := liblinphonearmv7
endif
include $(BUILD_SHARED_LIBRARY)
$(call import-module,android/cpufeatures)

View file

@ -44,7 +44,8 @@ LOCAL_SRC_FILES := \
linphonecall.c \
conference.c \
ec-calibrator.c \
linphone_tunnel.cc
linphone_tunnel_config.c \
message_storage.c
ifndef LINPHONE_VERSION
LINPHONE_VERSION = "Devel"
@ -55,13 +56,10 @@ LOCAL_CFLAGS += \
-DORTP_INET6 \
-DINET6 \
-DOSIP_MT \
-DHAVE_EXOSIP_GET_VERSION \
-DHAVE_EXOSIP_RESET_TRANSPORTS \
-DENABLE_TRACE \
-DHAVE_CONFIG_H \
-DLINPHONE_VERSION=\"$(LINPHONE_VERSION)\" \
-DLINPHONE_PLUGINS_DIR=\"\\tmp\" \
-DHAVE_EXOSIP_TRYLOCK=1 \
-DHAVE_EXOSIP_TLS_VERIFY_CERTIFICATE=1
LOCAL_CFLAGS += -DIN_LINPHONE
@ -79,6 +77,7 @@ endif
LOCAL_C_INCLUDES += \
$(LOCAL_PATH) \
$(LOCAL_PATH)/include \
$(LOCAL_PATH)/../build/android \
$(LOCAL_PATH)/../oRTP/include \
$(LOCAL_PATH)/../mediastreamer2/include \
$(LOCAL_PATH)/../../externals/exosip/include \
@ -97,15 +96,24 @@ LOCAL_STATIC_LIBRARIES := \
libosip2 \
libgsm
ifeq ($(BUILD_REMOTE_PROVISIONING),1)
LOCAL_STATIC_LIBRARIES += \
libxml2lpc \
liblpc2xml \
liblpxml2
endif
ifeq ($(BUILD_TUNNEL),1)
LOCAL_CFLAGS +=-DTUNNEL_ENABLED
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../tunnel/include $(LOCAL_PATH)/../../tunnel/src
LOCAL_SRC_FILES += TunnelManager.cc
LOCAL_SRC_FILES += linphone_tunnel.cc TunnelManager.cc
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
LOCAL_SHARED_LIBRARIES += libtunnelclient
else
LOCAL_STATIC_LIBRARIES += libtunnelclient
endif
else
LOCAL_SRC_FILES += linphone_tunnel_stubs.c
endif
@ -152,6 +160,11 @@ LOCAL_STATIC_LIBRARIES += \
endif
endif
ifeq ($(BUILD_UPNP),1)
LOCAL_CFLAGS += -DBUILD_UPNP
LOCAL_SRC_FILES += upnp.c
endif
LOCAL_STATIC_LIBRARIES += libspeex
ifeq ($(BUILD_SRTP), 1)

232
build/android/config.h Normal file
View file

@ -0,0 +1,232 @@
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define if building universal (internal helper macro) */
/* #undef AC_APPLE_UNIVERSAL_BUILD */
/* Define if tools enabled */
/* #undef BUILD_TOOLS */
/* Define if wizard enabled */
/* #undef BUILD_WIZARD */
/* Tells whether localisation is possible */
/* #undef ENABLE_NLS */
/* Defined when using gsm at nonstandard rates */
/* #undef ENABLE_NONSTANDARD_GSM */
/* The name of the gettext package name */
/* #undef GETTEXT_PACKAGE */
/* Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the
CoreFoundation framework. */
/* #undef HAVE_CFLOCALECOPYCURRENT */
/* Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in
the CoreFoundation framework. */
/* #undef HAVE_CFPREFERENCESCOPYAPPVALUE */
/* Define if the GNU dcgettext() function is already present or preinstalled.
*/
/* #undef HAVE_DCGETTEXT */
/* Define to 1 if you have the <dlfcn.h> header file. */
/* #undef HAVE_DLFCN_H */
/* Define if exosip dscp available */
/* #def HAVE_EXOSIP_DSCP */
/* Defined when eXosip_get_version is available */
#define HAVE_EXOSIP_GET_VERSION
/* Defined when eXosip_reset_transports is available */
#define HAVE_EXOSIP_RESET_TRANSPORTS
/* Defined when eXosip_tls_verify_certificate is available */
#define HAVE_EXOSIP_TLS_VERIFY_CERTIFICATE
/* Defined when eXosip_tls_verify_certificate is available */
/* #undef HAVE_EXOSIP_TLS_VERIFY_CN */
/* Defined when eXosip_get_socket is available */
#define HAVE_EXOSIP_TRYLOCK
/* If present, the getenv function allows fim to read environment variables.
*/
#define HAVE_GETENV 1
/* Define to 1 if you have the `getifaddrs' function. */
/* #undef HAVE_GETIFADDRS */
/* Tells wheter localisation is possible */
/* #undef HAVE_GETTEXT */
/* Define to 1 if you have the `get_current_dir_name' function. */
#define HAVE_GET_CURRENT_DIR_NAME 1
/* Defined when gtk osx is used */
/* #undef HAVE_GTK_OSX */
/* Define to 1 if you have the <history.h> header file. */
/* #undef HAVE_HISTORY_H */
/* Define if you have the iconv() function. */
/* #undef HAVE_ICONV */
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the `eXosip2' library (-leXosip2). */
/* #define HAVE_LIBEXOSIP2 */
/* Define to 1 if you have the `osip2' library (-losip2). */
/* #undef HAVE_LIBOSIP2 */
/* Define to 1 if you have the `osipparser2' library (-losipparser2). */
/* #undef HAVE_LIBOSIPPARSER2 */
/* Define to 1 if you have the `udev' library (-ludev). */
/* #undef HAVE_LIBUDEV */
/* Define to 1 if you have the <libudev.h> header file. */
/* #undef HAVE_LIBUDEV_H */
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* NOTIFY1 support */
/* #undef HAVE_NOTIFY1 */
/* NOTIFY4 support */
/* #undef HAVE_NOTIFY4 */
/* defined when compiling with readline support */
/* #undef HAVE_READLINE */
/* Define to 1 if you have the <readline.h> header file. */
/* #undef HAVE_READLINE_H */
/* Define to 1 if you have the <readline/history.h> header file. */
/* #undef HAVE_READLINE_HISTORY_H */
/* Define to 1 if you have the <readline/readline.h> header file. */
/* #undef HAVE_READLINE_READLINE_H */
/* Define if sighandler_t available */
/* #undef HAVE_SIGHANDLER_T */
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the `stpcpy' function. */
#define HAVE_STPCPY 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the `strndup' function. */
#define HAVE_STRNDUP 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to 1 if you have the <X11/Xlib.h> header file. */
#define HAVE_X11_XLIB_H 1
/* All supported languages */
/* #undef LINPHONE_ALL_LANGS */
/* Windows appdata subdir where linphonerc can be found */
/* #undef LINPHONE_CONFIG_DIR */
/* path of liblinphone plugins, not mediastreamer2 plugins */
/* #undef LINPHONE_PLUGINS_DIR */
/* Linphone's version number */
/* #undef LINPHONE_VERSION */
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#define LT_OBJDIR ".libs/"
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
/* #undef NO_MINUS_C_MINUS_O */
/* Name of package */
#define PACKAGE "linphone"
/* Define to the address where bug reports for this package should be sent. */
/* #undef PACKAGE_BUGREPORT */
/* Defines the place where data are found */
/* #undef PACKAGE_DATA_DIR */
/* Defines the place where locales can be found */
/* #undef PACKAGE_LOCALE_DIR */
/* Define to the full name of this package. */
#define PACKAGE_NAME "linphone"
/* Defines the place where linphone sounds are found */
/* #undef PACKAGE_SOUND_DIR */
/* Define to the full name and version of this package. */
/* #undef PACKAGE_STRING */
/* Define to the one symbol short name of this package. */
/* #undef PACKAGE_TARNAME */
/* Define to the home page for this package. */
/* #undef PACKAGE_URL */
/* Define to the version of this package. */
/* #undef PACKAGE_VERSION */
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Tell whether date_version.h must be used */
/* #undef USE_BUILDDATE_VERSION */
/* Version number of package */
/* #undef VERSION */
/* defined if video support is available */
/* #undef VIDEO_ENABLED */
/* Tell whether RSVP support should be compiled. */
/* #undef VINCENT_MAURY_RSVP */
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD
# if defined __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
# endif
#else
# ifndef WORDS_BIGENDIAN
/* # undef WORDS_BIGENDIAN */
# endif
#endif
/* Defined if we are compiling for arm processor */
/* #undef __ARM__ */
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
/* #undef inline */
#endif

View file

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

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

@ -0,0 +1,47 @@
##
## Android.mk -Android build script-
##
##
## Copyright (C) 2013 Belledonne Communications, Grenoble, France
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
##
LOCAL_PATH:= $(call my-dir)/../../tools
include $(CLEAR_VARS)
LOCAL_CPP_EXTENSION := .cc
LOCAL_SRC_FILES := \
lpc2xml.c \
lpc2xml_jni.cc \
LOCAL_CFLAGS += -DIN_LINPHONE
LOCAL_C_INCLUDES = \
$(LOCAL_PATH)/../coreapi \
$(LOCAL_PATH)/../oRTP/include \
$(LOCAL_PATH)/../mediastreamer2/include \
$(LOCAL_PATH)/../../externals/libxml2/include \
$(LOCAL_PATH)/../../externals/build/libxml2 \
LOCAL_SHARED_LIBRARIES = \
# liblinphonenoneon \
# liblinphone \
LOCAL_MODULE := liblpc2xml
include $(BUILD_STATIC_LIBRARY)

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

@ -0,0 +1,47 @@
##
## Android.mk -Android build script-
##
##
## Copyright (C) 2013 Belledonne Communications, Grenoble, France
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
##
LOCAL_PATH:= $(call my-dir)/../../tools
include $(CLEAR_VARS)
LOCAL_CPP_EXTENSION := .cc
LOCAL_SRC_FILES := \
xml2lpc.c \
xml2lpc_jni.cc \
LOCAL_CFLAGS += -DIN_LINPHONE
LOCAL_C_INCLUDES = \
$(LOCAL_PATH)/../coreapi \
$(LOCAL_PATH)/../oRTP/include \
$(LOCAL_PATH)/../mediastreamer2/include \
$(LOCAL_PATH)/../../externals/libxml2/include \
$(LOCAL_PATH)/../../externals/build/libxml2 \
LOCAL_SHARED_LIBRARIES = \
# liblinphonenoneon \
# liblinphone \
LOCAL_MODULE := libxml2lpc
include $(BUILD_STATIC_LIBRARY)

View file

@ -1,4 +1,5 @@
export EXTRA_ARGS="--workdir $bundle_res"
export GIO_EXTRA_MODULES="$bundle_res/lib/gio/modules"
export GIO_EXTRA_MODULES="$bundle_lib/gio/modules"
export PANGO_LIBDIR="$bundle_lib"
export PANGO_SYSCONFDIR="$bundle_etc"

View file

@ -0,0 +1,26 @@
--- libiconv-1.14.orig/lib/iconv.c 2013-03-14 16:30:50.000000000 +0100
+++ libiconv-1.14/lib/iconv.c 2013-03-15 10:24:38.000000000 +0100
@@ -607,4 +607,23 @@
strong_alias (libiconv_close, iconv_close)
#endif
+#undef iconv_open
+#undef iconv
+#undef iconv_close
+
+LIBICONV_DLL_EXPORTED iconv_t iconv_open (const char* tocode, const char* fromcode){
+ return libiconv_open(tocode,fromcode);
+}
+
+LIBICONV_DLL_EXPORTED size_t iconv (iconv_t icd,
+ ICONV_CONST char* * inbuf, size_t *inbytesleft,
+ char* * outbuf, size_t *outbytesleft){
+ return libiconv(icd,inbuf,inbytesleft,outbuf,outbytesleft);
+}
+
+LIBICONV_DLL_EXPORTED int iconv_close (iconv_t icd){
+ return libiconv_close(icd);
+}
+
+
#endif

View file

@ -1,6 +1,6 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT([linphone],[3.5.99.0],[linphone-developers@nongnu.org])
AC_INIT([linphone],[3.6.1],[linphone-developers@nongnu.org])
AC_CANONICAL_SYSTEM
AC_CONFIG_SRCDIR([coreapi/linphonecore.c])
@ -29,7 +29,7 @@ AC_SUBST(LINPHONE_VERSION)
AC_MSG_NOTICE([$PACKAGE_NAME-$PACKAGE_VERSION A full featured audio/video sip phone.])
AC_MSG_NOTICE([licensed under the terms of the General Public License (GPL)])
AM_INIT_AUTOMAKE
AM_INIT_AUTOMAKE([1.9 tar-pax])
AC_SUBST([LIBTOOL_DEPS])
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],)
AC_SUBST([docdir], [${datadir}/doc])
@ -46,12 +46,12 @@ AM_CONDITIONAL(HAVE_MD5SUM,test -n $MD5SUM)
case $target in
*mingw32ce)
CFLAGS="$CFLAGS -D_WIN32_WCE -DORTP_STATIC -D_WIN32_WINNT=0x0501"
CXXFLAGS="$CXXFLAGS -DORTP_STATIC -D_WIN32_WINNT=0x0501"
LIBS="$LIBS -lws2 -liphlpapi"
CFLAGS="$CFLAGS -D_WIN32_WCE -DORTP_STATIC -D_WIN32_WINNT=0x0501"
CXXFLAGS="$CXXFLAGS -DORTP_STATIC -D_WIN32_WINNT=0x0501"
LIBS="$LIBS -lws2 -liphlpapi"
mingw_found=yes
mingwce_found=yes
;;
;;
*mingw*)
CFLAGS="$CFLAGS -DORTP_STATIC -D_WIN32_WINNT=0x0501 "
CXXFLAGS="$CXXFLAGS -DORTP_STATIC -D_WIN32_WINNT=0x0501"
@ -60,17 +60,17 @@ case $target in
CONSOLE_FLAGS="-mconsole"
mingw_found=yes
;;
armv6-apple-darwin|armv7-apple-darwin|i386-apple-darwin|armv7s-apple-darwin)
CFLAGS="$CFLAGS -DTARGET_OS_IPHONE "
build_tests=no
ios_found=yes
;;
x86_64-apple-darwin*|i686-apple-darwin*)
MSPLUGINS_CFLAGS=""
armv6-apple-darwin|armv7-apple-darwin|i386-apple-darwin|armv7s-apple-darwin)
CFLAGS="$CFLAGS -DTARGET_OS_IPHONE "
build_tests=no
ios_found=yes
;;
x86_64-apple-darwin*|i686-apple-darwin*)
MSPLUGINS_CFLAGS=""
dnl use macport installation
ACLOCAL_MACOS_FLAGS="-I /opt/local/share/aclocal"
build_macos=yes
;;
;;
esac
@ -82,21 +82,38 @@ dnl localization tools
IT_PROG_INTLTOOL([0.40], [no-xml])
AM_CONDITIONAL(BUILD_TESTS,test x$build_tests != xno)
dnl Initialize libtool
LT_INIT([win32-dll shared disable-static])
AC_CONFIG_COMMANDS([libtool-hacking],[
if test "$mingw_found" = "yes" ; then
echo "Hacking libtool to work with mingw..."
sed -e 's/\*\" \$a_deplib \"\*/\*/' < ./libtool > libtool.tmp
cp -f ./libtool.tmp ./libtool
rm -f ./libtool.tmp
dnl Enable library dependencies linking
AC_ARG_ENABLE(deplibs-link,
[AS_HELP_STRING([--disable-deplibs-link ], [Disable library dependencies linking (might break builds)])],
[enable_deplibs_linking="$enableval"],
[enable_deplibs_linking="yes"]
)
AC_MSG_NOTICE([Enable library dependencies linking: $enable_interlib_deps])
if test "${enable_deplibs_linking}" == "yes"; then
link_all_deplibs=yes
link_all_deplibs_CXX=yes
else
link_all_deplibs=no
link_all_deplibs_CXX=no
fi
],[mingw_found=$mingw_found])
AC_CONFIG_COMMANDS([libtool-hacking],
[if test "$mingw_found" = "yes" ; then
echo "Hacking libtool to work with mingw..."
sed -e 's/\*\" \$a_deplib \"\*/\*/' < ./libtool > libtool.tmp
cp -f ./libtool.tmp ./libtool
rm -f ./libtool.tmp
fi],
[mingw_found=$mingw_found]
)
dnl Add the languages which your application supports here.
PKG_PROG_PKG_CONFIG
ALL_LINGUAS="fr it de ja es pl cs nl sv pt_BR hu ru zh_CN nb_NO zh_TW he"
ALL_LINGUAS="fr it de ja es pl cs nl sv pt_BR hu ru zh_CN nb_NO zh_TW he sr"
AC_SUBST(ALL_LINGUAS)
AC_DEFINE_UNQUOTED(LINPHONE_ALL_LANGS, "$ALL_LINGUAS", [All supported languages])
@ -123,62 +140,101 @@ dnl AC_CHECK_LIB(intl,libintl_gettext)
AC_CHECK_FUNCS([get_current_dir_name strndup stpcpy] )
AC_ARG_ENABLE(x11,
[AS_HELP_STRING([--disable-x11], [Disable X11 support (default=no)])],
[case "${enableval}" in
yes) enable_x11=true ;;
no) enable_x11=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --disable-x11) ;;
esac],[enable_x11=true])
[AS_HELP_STRING([--disable-x11], [Disable X11 support (default=no)])],
[case "${enableval}" in
yes) enable_x11=true ;;
no) enable_x11=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --disable-x11) ;;
esac],
[enable_x11=true]
)
dnl conditionnal build of console interface.
AC_ARG_ENABLE(console_ui,
[AS_HELP_STRING([--enable-console_ui=[yes/no]], [Turn on or off compilation of console interface (default=yes)])],
[case "${enableval}" in
yes) console_ui=true ;;
no) console_ui=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-console_ui) ;;
esac],[console_ui=true])
[AS_HELP_STRING([--enable-console_ui=[yes/no]], [Turn on or off compilation of console interface (default=yes)])],
[case "${enableval}" in
yes) console_ui=true ;;
no) console_ui=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-console_ui) ;;
esac],
[console_ui=true]
)
dnl conditionnal build of tools.
AC_ARG_ENABLE(tools,
[AS_HELP_STRING([--enable-tools=[yes/no]], [Turn on or off compilation of console interface (default=yes)])],
[case "${enableval}" in
yes) build_tools=true ;;
no) build_tools=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-tools) ;;
esac],[build_tools=check])
[AS_HELP_STRING([--enable-tools=[yes/no]], [Turn on or off compilation of console interface (default=yes)])],
[case "${enableval}" in
yes) build_tools=true ;;
no) build_tools=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-tools) ;;
esac],
[build_tools=check]
)
dnl check for installed version of libupnp
AC_ARG_ENABLE(upnp,
[AS_HELP_STRING([--disable-upnp], [Disable uPnP support])],
[case "${enableval}" in
yes) build_upnp=true ;;
no) build_upnp=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --disable-upnp) ;;
esac],
[build_upnp=auto]
)
if test "$build_upnp" != "false" ; then
PKG_CHECK_MODULES([LIBUPNP], [libupnp],
[if pkg-config --atleast-version=1.6 "libupnp < 1.7"; then
build_upnp=true
else
AC_MSG_ERROR([libupnp >= 1.6 < 1.5 required.])
fi],
[if test "$build_upnp" == "true" ; then
AC_MSG_ERROR([libupnp not found.])
else
build_upnp=false
fi]
)
fi
AM_CONDITIONAL(BUILD_UPNP, test x$build_upnp != xfalse)
if test "$build_upnp" != "false" ; then
AC_DEFINE(BUILD_UPNP, 1, [Define if upnp enabled])
fi
dnl check libxml2 (needed for tools)
if test "$build_tools" != "false" ; then
PKG_CHECK_MODULES(LIBXML2, [libxml-2.0 >= 2.9 ],[],
[
if test "$build_tools" = "true" ; then
PKG_CHECK_MODULES(LIBXML2, [libxml-2.0],[],
[if test "$build_tools" = "true" ; then
AC_MSG_ERROR([Could not found libxml2, tools cannot be compiled.])
else
build_tools=false
fi
])
fi]
)
fi
AM_CONDITIONAL(BUILD_TOOLS, test x$build_tools != xfalse)
if test "$build_tools" != "false" ; then
build_tools=true
AC_DEFINE(BUILD_TOOLS, 1, [Define if tools enabled] )
build_tools=true
AC_DEFINE(BUILD_TOOLS, 1, [Define if tools enabled] )
fi
dnl conditionnal build of gtk interface.
AC_ARG_ENABLE(gtk_ui,
[AS_HELP_STRING([--enable-gtk_ui=[yes/no]], [Turn on or off compilation of gtk interface (default=yes)])],
[case "${enableval}" in
yes) gtk_ui=true ;;
no) gtk_ui=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-gtk_ui) ;;
esac],[gtk_ui=true])
[AS_HELP_STRING([--enable-gtk_ui=[yes/no]], [Turn on or off compilation of gtk interface (default=yes)])],
[case "${enableval}" in
yes) gtk_ui=true ;;
no) gtk_ui=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-gtk_ui) ;;
esac],
[gtk_ui=true]
)
if test "$gtk_ui" = "true" ; then
PKG_CHECK_MODULES(LIBGTK, gtk+-2.0 >= 2.18.0 gthread-2.0)
if test "$enable_x11" = "false" ; then
PKG_CHECK_MODULES(LIBGTKMAC,[ige-mac-integration >= 0.9.7 ])
PKG_CHECK_MODULES(LIBGTKMAC,[gtk-mac-integration >= 2.0.1])
AC_DEFINE([HAVE_GTK_OSX],[1],[Defined when gtk osx is used])
fi
else
@ -186,33 +242,35 @@ else
fi
AC_ARG_ENABLE(notify,
[AS_HELP_STRING([--enable-notify=[yes/no]], [Enable libnotify support (default=yes)])],
[case "${enableval}" in
yes) notify=true ;;
no) notify=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-notify) ;;
esac],[notify=true])
[AS_HELP_STRING([--enable-notify=[yes/no]], [Enable libnotify support (default=yes)])],
[case "${enableval}" in
yes) notify=true ;;
no) notify=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-notify) ;;
esac],
[notify=true]
)
dnl conditionnal build of the notify library
if test "$gtk_ui" = "true" ; then
if test "$notify" = "true"; then
PKG_CHECK_MODULES([NOTIFY4], [libnotify >= 0.7.0 ], [found_notify4=yes], foo=bar)
case "$found_notify4" in
yes)
yes)
AC_SUBST(NOTIFY4_CFLAGS)
AC_SUBST(NOTIFY4_LIBS)
AC_DEFINE([HAVE_NOTIFY4],[1],[NOTIFY4 support])
esac
PKG_CHECK_MODULES([NOTIFY1], [libnotify < 0.7.0], [found_notify1=yes], foo=bar)
case "$found_notify1" in
yes)
AC_SUBST(NOTIFY1_CFLAGS)
AC_SUBST(NOTIFY1_LIBS)
AC_DEFINE([HAVE_NOTIFY1],[1],[NOTIFY1 support])
esac
PKG_CHECK_MODULES([NOTIFY1], [libnotify < 0.7.0], [found_notify1=yes], foo=bar)
case "$found_notify1" in
yes)
AC_SUBST(NOTIFY1_CFLAGS)
AC_SUBST(NOTIFY1_LIBS)
AC_DEFINE([HAVE_NOTIFY1],[1],[NOTIFY1 support])
esac
else
NotifyNotification *n;
NotifyNotification *n;
echo "Libnotify support is disabled."
fi
fi
@ -221,37 +279,41 @@ dnl os-specific problems not handled by existing macros.
case "$host_os" in
*freebsd*)
LDFLAGS="$LDFLAGS -pthread"
;;
;;
esac
case "$host_cpu" in
*arm*)
AC_DEFINE(__ARM__,1,[Defined if we are compiling for arm processor])
use_arm_toolchain=yes
;;
;;
esac
AC_ARG_WITH(configdir,
[AS_HELP_STRING([--with-configdir], [Set a APPDATA subdir where linphone is supposed to find its config (windows only)])],
[ configdir=${withval}],[ configdir="Linphone" ])
[AS_HELP_STRING([--with-configdir], [Set a APPDATA subdir where linphone is supposed to find its config (windows only)])],
[ configdir=${withval}],[ configdir="Linphone" ])
AC_DEFINE_UNQUOTED(LINPHONE_CONFIG_DIR,"$configdir",[Windows appdata subdir where linphonerc can be found])
AC_ARG_ENABLE(relativeprefix,
[AS_HELP_STRING([--enable-relativeprefix], [Build a linphone that finds its resources relatively to the directory where it is installed])],
[case "${enableval}" in
yes) relativeprefix=yes ;;
no) relativeprefix=no ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-relativeprefix) ;;
esac],[relativeprefix=guess])
[AS_HELP_STRING([--enable-relativeprefix], [Build a linphone that finds its resources relatively to the directory where it is installed])],
[case "${enableval}" in
yes) relativeprefix=yes ;;
no) relativeprefix=no ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-relativeprefix) ;;
esac],
[relativeprefix=guess]
)
AC_ARG_ENABLE(date,
[AS_HELP_STRING([--enable-date], [Use build date in internal version number])],
[case "${enableval}" in
yes) use_date=yes ;;
no) use_date=no ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-date) ;;
esac],[use_date=no])
[AS_HELP_STRING([--enable-date], [Use build date in internal version number])],
[case "${enableval}" in
yes) use_date=yes ;;
no) use_date=no ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-date) ;;
esac],
[use_date=no]
)
if test x$use_date = xyes ; then
AC_DEFINE(USE_BUILDDATE_VERSION,1,[Tell whether date_version.h must be used])
@ -260,12 +322,14 @@ fi
dnl enable ipv6 support
AC_ARG_ENABLE(ipv6,
[AS_HELP_STRING([--enable-ipv6], [Turn on ipv6 support])],
[case "${enableval}" in
yes) ipv6=true;;
no) ipv6=false;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-ipv6) ;;
esac],[ipv6=true])
[AS_HELP_STRING([--enable-ipv6], [Turn on ipv6 support])],
[case "${enableval}" in
yes) ipv6=true;;
no) ipv6=false;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-ipv6) ;;
esac],
[ipv6=true]
)
IPV6_CFLAGS=
if test x$ipv6 = xtrue ; then
IPV6_CFLAGS=-DINET6
@ -274,29 +338,35 @@ AC_SUBST(IPV6_CFLAGS)
dnl enable timestamp support
AC_ARG_ENABLE(ntp-timestamp,
[AS_HELP_STRING([--enable-ntp-timestamp], [Turn on NTP timestamping on received packet])],
[case "${enableval}" in
yes) ntptimestamp=true;;
no) ntptimestamp=false;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-ntp-timestamp) ;;
esac],[ntptimestamp=false])
[AS_HELP_STRING([--enable-ntp-timestamp], [Turn on NTP timestamping on received packet])],
[case "${enableval}" in
yes) ntptimestamp=true;;
no) ntptimestamp=false;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-ntp-timestamp) ;;
esac],
[ntptimestamp=false]
)
AC_ARG_ENABLE(debug,
[AS_HELP_STRING([--enable-debug=[yes/no]], [Enables the display of traces showing the execution of the library. (default=yes)])],
[case "${enableval}" in
yes) debug_enabled=yes;;
no) debug_enabled=no;;
*) AC_MSG_ERROR("Bad value for --enable-debug");;
esac],[debug_enabled=no])
[AS_HELP_STRING([--enable-debug=[yes/no]], [Enables the display of traces showing the execution of the library. (default=yes)])],
[case "${enableval}" in
yes) debug_enabled=yes;;
no) debug_enabled=no;;
*) AC_MSG_ERROR("Bad value for --enable-debug");;
esac],
[debug_enabled=no]
)
dnl enable truespeech codec support
AC_ARG_ENABLE(truespeech,
[AS_HELP_STRING([--enable-truespeech], [Turn on TrueSpeech support (x86 only)])],
[case "${enableval}" in
yes) truespeech=true;;
no) truespeech=false;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-truespeech) ;;
esac],[truespeech=false])
[AS_HELP_STRING([--enable-truespeech], [Turn on TrueSpeech support (x86 only)])],
[case "${enableval}" in
yes) truespeech=true;;
no) truespeech=false;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-truespeech) ;;
esac],
[truespeech=false]
)
TRUESPEECH_CFLAGS=
if test x$truespeech = xtrue ; then
TRUESPEECH_CFLAGS=-DTRUESPEECH
@ -305,21 +375,24 @@ AC_SUBST(TRUESPEECH_CFLAGS)
AM_CONDITIONAL([BUILD_TRUESPEECH], [test x$truespeech = xtrue])
AC_ARG_ENABLE(nonstandard-gsm,
[AS_HELP_STRING([--enable-nonstandard-gsm], [Enable GSM codec at nonstandard rates (11025hz, 16000hz)])],
[case "${enableval}" in
yes) exotic_gsm=yes
AC_DEFINE(ENABLE_NONSTANDARD_GSM,1,[Defined when using gsm at nonstandard rates])
;;
no) exotic_gsm=no ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-nonstandard-gsm) ;;
esac],[exotic_gsm=no])
[AS_HELP_STRING([--enable-nonstandard-gsm], [Enable GSM codec at nonstandard rates (11025hz, 16000hz)])],
[case "${enableval}" in
yes)
exotic_gsm=yes
AC_DEFINE(ENABLE_NONSTANDARD_GSM,1,[Defined when using gsm at nonstandard rates])
;;
no) exotic_gsm=no ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-nonstandard-gsm) ;;
esac],
[exotic_gsm=no]
)
dnl support for RSVP (by Vincent Maury)
AC_ARG_ENABLE(rsvp,
[AS_HELP_STRING([--enable-rsvp], [Enable support for QoS reservations.])],
AC_DEFINE(VINCENT_MAURY_RSVP,1,[Tell whether RSVP support
should be compiled.]) )
[AS_HELP_STRING([--enable-rsvp], [Enable support for QoS reservations.])],
AC_DEFINE(VINCENT_MAURY_RSVP,1,[Tell whether RSVP support should be compiled.])
)
if test "x${prefix}" = "xNONE"; then
package_prefix=${ac_default_prefix}
@ -356,12 +429,14 @@ LP_CHECK_OSIP2
dnl conditionnal build for ssl
AC_ARG_ENABLE(ssl,
[AS_HELP_STRING([--enable-ssl], [Turn on ssl support compiling. Required for sip tls. (default=false)])],
[case "${enableval}" in
yes) build_ssl=true ;;
no) build_ssl=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-ssl) ;;
esac],[build_ssl=false])
[AS_HELP_STRING([--enable-ssl], [Turn on ssl support compiling. Required for sip tls. (default=false)])],
[case "${enableval}" in
yes) build_ssl=true ;;
no) build_ssl=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-ssl) ;;
esac],
[build_ssl=false]
)
if test "$build_ssl" = "true"; then
PKG_CHECK_MODULES(OPENSSL, libssl >= 0.9.8)
@ -369,29 +444,20 @@ fi
dnl setup flags for exosip library
LP_SETUP_EXOSIP
dnl check exosip support of DSCP in exosip
AC_MSG_CHECKING([for DSCP support in exosip])
AC_TRY_COMPILE([#include <eXosip2/eXosip.h>],
[int dscp=0;eXosip_set_option(EXOSIP_OPT_SET_DSCP,&dscp);],
has_exosip_dscp=yes,has_exosip_dscp=no)
AC_MSG_RESULT($has_exosip_dscp)
if test "$has_exosip_dscp" = "yes" ; then
AC_DEFINE( HAVE_EXOSIP_DSCP, 1, [Define if exosip dscp available] )
fi
if test "$console_ui" = "true" ; then
dnl check gnu readline
LP_CHECK_READLINE
dnl check gnu readline
LP_CHECK_READLINE
else
echo "Console interface compilation is disabled."
echo "Console interface compilation is disabled."
fi
AC_WORDS_BIGENDIAN
AC_ARG_ENABLE([speex],
AS_HELP_STRING([--disable-speex], [Disable speex support]),
[], [enable_speex=yes])
AS_HELP_STRING([--disable-speex], [Disable speex support]),
[],
[enable_speex=yes]
)
if test "x$enable_speex" = "xyes"; then
dnl normaly this should only by done by mediastreamer2/configure.ac
dnl but to workaround bugs when cross-compiling for arm-linux,
@ -403,16 +469,20 @@ fi
dnl conditionnal build of video support
AC_ARG_ENABLE(video,
[AS_HELP_STRING([--enable-video], [Turn on video support compiling])],
[case "${enableval}" in
yes) video=true ;;
no) video=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-video) ;;
esac],[video=true])
[AS_HELP_STRING([--enable-video], [Turn on video support compiling])],
[case "${enableval}" in
yes) video=true ;;
no) video=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-video) ;;
esac],
[video=true]
)
AC_ARG_WITH( ffmpeg,
[AS_HELP_STRING([--with-ffmpeg], [Sets the installation prefix of ffmpeg, needed for video support. (default=/usr)])],
[ ffmpegdir=${withval}],[ ffmpegdir=/usr ])
AC_ARG_WITH(ffmpeg,
[AS_HELP_STRING([--with-ffmpeg], [Sets the installation prefix of ffmpeg, needed for video support. (default=/usr)])],
[ ffmpegdir=${withval}],
[ ffmpegdir=/usr ]
)
if test "$video" = "true"; then
@ -429,29 +499,35 @@ if test "$video" = "true"; then
fi
AC_ARG_ENABLE(alsa,
[AS_HELP_STRING([--enable-alsa], [Turn on alsa native support compiling])],
[case "${enableval}" in
yes) alsa=true ;;
no) alsa=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-alsa) ;;
esac],[alsa=true])
[AS_HELP_STRING([--enable-alsa], [Turn on alsa native support compiling])],
[case "${enableval}" in
yes) alsa=true ;;
no) alsa=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-alsa) ;;
esac],
[alsa=true]
)
AC_ARG_ENABLE(zrtp,
[AS_HELP_STRING([--enable-zrtp], [Turn on zrtp support])],
[case "${enableval}" in
yes) zrtp=true ;;
no) zrtp=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-zrtp) ;;
esac],[zrtp=false])
[AS_HELP_STRING([--enable-zrtp], [Turn on zrtp support])],
[case "${enableval}" in
yes) zrtp=true ;;
no) zrtp=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-zrtp) ;;
esac],
[zrtp=false]
)
AC_ARG_ENABLE(portaudio,
[AS_HELP_STRING([--enable-portaudio], [Turn on portaudio native support compiling])],
[case "${enableval}" in
yes) portaudio=true ;;
no) portaudio=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-portaudio) ;;
esac],[portaudio=false])
[AS_HELP_STRING([--enable-portaudio], [Turn on portaudio native support compiling])],
[case "${enableval}" in
yes) portaudio=true ;;
no) portaudio=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-portaudio) ;;
esac],
[portaudio=false]
)
dnl build console if required
AM_CONDITIONAL(BUILD_CONSOLE, test x$console_ui = xtrue)
@ -474,44 +550,44 @@ AC_TRY_COMPILE([#include <signal.h>],[sighandler_t *f;],
has_sighandler_t=yes,has_sighandler_t=no)
AC_MSG_RESULT($has_sighandler_t)
if test "$has_sighandler_t" = "yes" ; then
AC_DEFINE( HAVE_SIGHANDLER_T, 1, [Define if sighandler_t available] )
AC_DEFINE( HAVE_SIGHANDLER_T, 1, [Define if sighandler_t available] )
fi
AC_ARG_ENABLE(assistant,
[AS_HELP_STRING([--enable-assistant], [Turn on assistant compiling])],
[case "${enableval}" in
yes) build_wizard=true ;;
no) build_wizard=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-assistant) ;;
esac],[build_wizard=check])
[AS_HELP_STRING([--enable-assistant], [Turn on assistant compiling])],
[case "${enableval}" in
yes) build_wizard=true ;;
no) build_wizard=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-assistant) ;;
esac],
[build_wizard=check]
)
dnl check libsoup (needed for wizard)
if test "$build_wizard" != "false" ; then
PKG_CHECK_MODULES(LIBSOUP, [libsoup-2.4 >= 2.26],[],
[
if test "$build_wizard" = "true" ; then
[if test "$build_wizard" = "true" ; then
AC_MSG_ERROR([Could not found libsoup, assistant cannot be compiled.])
else
build_wizard=false
fi
])
fi]
)
fi
if test "$build_wizard" != "false" ; then
PKG_CHECK_MODULES(LIBGTKWIZARD, [gtk+-2.0 >= 2.22.0],[],
[
if test "$build_wizard" = "true" ; then
[if test "$build_wizard" = "true" ; then
AC_MSG_ERROR([gtk+-2.0 < 2.22.0, assistant cannot be compiled.])
else
build_wizard=false
fi
])
fi]
)
fi
AC_SUBST(LIBSOUP_CFLAGS)
AC_SUBST(LIBSOUP_LIBS)
AM_CONDITIONAL(BUILD_WIZARD, test x$build_wizard != xfalse)
if test "$build_wizard" != "false" ; then
build_wizard=true
AC_DEFINE(BUILD_WIZARD, 1, [Define if wizard enabled] )
build_wizard=true
AC_DEFINE(BUILD_WIZARD, 1, [Define if wizard enabled] )
fi
AC_CHECK_HEADERS(libudev.h)
@ -523,9 +599,9 @@ AC_CHECK_LIB(udev,udev_new)
AC_ARG_ENABLE(strict,
AC_HELP_STRING([--enable-strict],
[Build with stricter options (gcc only) @<:@yes@:>@]),[
strictness="${enableval}"],[strictness=yes]
AC_HELP_STRING([--enable-strict], [Build with stricter options (gcc only) @<:@yes@:>@]),
[strictness="${enableval}"],
[strictness=yes]
)
STRICT_OPTIONS="-Wall "
@ -540,26 +616,26 @@ AC_SUBST(STRICT_OPTIONS)
top_srcdir=`dirname $0`
AC_ARG_ENABLE([external-mediastreamer],
[AS_HELP_STRING([--enable-external-mediastreamer],[Use external mediastreamer library])],,
[enable_external_mediastreamer=no])
[AS_HELP_STRING([--enable-external-mediastreamer],[Use external mediastreamer library])],,
[enable_external_mediastreamer=no]
)
AS_CASE($enable_external_mediastreamer,
[yes],[
PKG_CHECK_MODULES([MEDIASTREAMER], [mediastreamer])
MS2_VERSION=`$PKG_CONFIG --modversion mediastreamer`
],
[no],[
AC_CONFIG_SUBDIRS( mediastreamer2 )
MEDIASTREAMER_DIR=${top_srcdir}/mediastreamer2
MEDIASTREAMER_CFLAGS="-I\$(top_srcdir)/mediastreamer2/include"
MEDIASTREAMER_LIBS="\$(top_builddir)/mediastreamer2/src/libmediastreamer_base.la \$(top_builddir)/mediastreamer2/src/libmediastreamer_voip.la"
[yes],
[PKG_CHECK_MODULES([MEDIASTREAMER], [mediastreamer])
MS2_VERSION=`$PKG_CONFIG --modversion mediastreamer`],
[no],
[AC_CONFIG_SUBDIRS( mediastreamer2 )
MEDIASTREAMER_DIR=${top_srcdir}/mediastreamer2
MEDIASTREAMER_CFLAGS="-I\$(top_srcdir)/mediastreamer2/include"
MEDIASTREAMER_LIBS="\$(top_builddir)/mediastreamer2/src/libmediastreamer_base.la \$(top_builddir)/mediastreamer2/src/libmediastreamer_voip.la"
dnl need to temporary change quotes to allow square brackets
changequote(<<, >>)
MS2_VERSION=`grep -e '^.C_INIT(' $MEDIASTREAMER_DIR/configure.ac | sed -e 's:\([^(]\+\)(\[mediastreamer\],\[\(.*\)\]):\2:g'`
changequote([, ])
MS2_DIR=mediastreamer2
],
[AC_MSG_ERROR([bad value '${enable_external_mediastreamer}' for --enable-external-mediastreamer])])
changequote(<<, >>)
MS2_VERSION=`grep -e '^.C_INIT(' $MEDIASTREAMER_DIR/configure.ac | sed -e 's:\([^(]\+\)(\[mediastreamer\],\[\(.*\)\]):\2:g'`
changequote([, ])
MS2_DIR=mediastreamer2],
[AC_MSG_ERROR([bad value '${enable_external_mediastreamer}' for --enable-external-mediastreamer])]
)
AC_SUBST(MEDIASTREAMER_CFLAGS)
AC_SUBST(MEDIASTREAMER_LIBS)
@ -569,31 +645,50 @@ AC_SUBST([MS2_DIR])
AC_ARG_ENABLE(tunnel,
[AS_HELP_STRING([--enable-tunnel=[yes/no]], [Turn on compilation of tunnel support (default=no)])],
[case "${enableval}" in
yes) enable_tunnel=true ;;
no) enable_tunnel=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-tunnel) ;;
esac],[enable_tunnel=false])
[AS_HELP_STRING([--enable-tunnel=[yes/no]], [Turn on compilation of tunnel support (default=no)])],
[case "${enableval}" in
yes) enable_tunnel=true ;;
no) enable_tunnel=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-tunnel) ;;
esac],
[enable_tunnel=false]
)
AM_CONDITIONAL(BUILD_TUNNEL, test x$enable_tunnel = xtrue)
if test x$enable_tunnel = xtrue; then
PKG_CHECK_MODULES(TUNNEL, tunnel >= 0.3.3)
TUNNEL_CFLAGS+="-DTUNNEL_ENABLED"
AC_SUBST(TUNNEL_CFLAGS)
AC_SUBST(TUNNEL_LIBS)
PKG_CHECK_MODULES(TUNNEL, tunnel >= 0.3.3)
AC_DEFINE(TUNNEL_ENABLED,1,[Tells tunnel extension is built-in])
fi
AC_ARG_ENABLE(msg-storage,
[AS_HELP_STRING([--enable-msg-storage=[yes/no]], [Turn on compilation of message storage (default=auto)])],
[case "${enableval}" in
yes) enable_msg_storage=true ;;
no) enable_msg_storage=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-msg-storage) ;;
esac],
[enable_msg_storage=auto]
)
AM_CONDITIONAL(BUILD_MSG_STORAGE, test x$enable_msg_storage = xtrue)
if test x$enable_msg_storage != xfalse; then
PKG_CHECK_MODULES(SQLITE3,[ sqlite3 >= 3.7.0],[
SQLITE3_CFLAGS+="-DMSG_STORAGE_ENABLED"
AC_SUBST(SQLITE3_CFLAGS)
AC_SUBST(SQLITE3_LIBS)
enable_msg_storage=true
],[
if test x$enable_msg_storage = xtrue; then
AC_MSG_ERROR([sqlite3 required for message storage not found.])
fi
enable_msg_storage=false
] )
fi
dnl check for db2html (docbook) to generate html user manual
AC_CHECK_PROG(have_sgmltools,sgmltools, yes, no)
AC_CHECK_PROG(have_sgmltools, sgmltools, yes, no)
AM_CONDITIONAL(ENABLE_MANUAL, test x$have_sgmltools$build_manual = xyesyes )
dnl for external use of linphone libs
@ -606,19 +701,21 @@ fi
AC_SUBST(LINPHONE_CFLAGS)
AC_SUBST(LINPHONE_LIBS)
AC_DEFINE_UNQUOTED(LINPHONE_VERSION,"$PACKAGE_VERSION",[Linphone's version number])
AC_DEFINE_UNQUOTED(LINPHONE_VERSION, "$PACKAGE_VERSION", [Linphone\'s version number])
AC_DEFINE_UNQUOTED(LINPHONE_PLUGINS_DIR, "${package_prefix}/lib/liblinphone/plugins" ,[path of liblinphone plugins, not mediastreamer2 plugins])
LINPHONE_PLUGINS_DIR="${package_prefix}/lib/liblinphone/plugins"
AC_SUBST(LINPHONE_PLUGINS_DIR)
AC_ARG_ENABLE(external-ortp,
[AS_HELP_STRING([--enable-external-ortp], [Use external oRTP library])],
[case "${enableval}" in
yes) external_ortp=true ;;
no) external_ortp=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-external-ortp) ;;
esac],[external_ortp=false])
[AS_HELP_STRING([--enable-external-ortp], [Use external oRTP library])],
[case "${enableval}" in
yes) external_ortp=true ;;
no) external_ortp=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --enable-external-ortp) ;;
esac],
[external_ortp=false]
)
if test "$external_ortp" = 'true'; then
PKG_CHECK_MODULES([ORTP], [ortp])
@ -631,7 +728,7 @@ else
ORTP_CFLAGS="$ORTP_CFLAGS -DORTP_BIGENDIAN"
fi
if test x$ntptimestamp = xtrue ; then
ORTP_CFLAGS="$ORTP_CFLAGS -DORTP_TIMESTAMP"
ORTP_CFLAGS="$ORTP_CFLAGS -DORTP_TIMESTAMP"
fi
ORTP_DIR=oRTP
changequote(<<, >>)
@ -644,12 +741,14 @@ AC_SUBST([ORTP_VERSION])
AC_SUBST([ORTP_DIR])
AC_ARG_ENABLE(tests_enabled,
[AS_HELP_STRING([--disable-tests], [Disable compilation of tests])],
[case "${enableval}" in
yes) tests_enabled=true ;;
no) tests_enabled=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --disable-tests) ;;
esac],[tests_enabled=false])
[AS_HELP_STRING([--disable-tests], [Disable compilation of tests])],
[case "${enableval}" in
yes) tests_enabled=true ;;
no) tests_enabled=false ;;
*) AC_MSG_ERROR(bad value ${enableval} for --disable-tests) ;;
esac],
[tests_enabled=false]
)
AM_CONDITIONAL(ENABLE_TESTS, test x$tests_enabled = xyes)
@ -663,44 +762,46 @@ AM_CONDITIONAL(HAVE_DOXYGEN, test $DOXYGEN != false)
AC_CONFIG_FILES([
Makefile
build/Makefile
build/macos/Makefile
build/macos/Info-linphone.plist
m4/Makefile
po/Makefile.in
pixmaps/Makefile
coreapi/Makefile
coreapi/help/Makefile
coreapi/help/Doxyfile
gtk/Makefile
console/Makefile
daemon/Makefile
share/Makefile
share/C/Makefile
share/fr/Makefile
share/it/Makefile
share/ja/Makefile
share/cs/Makefile
share/xml/Makefile
share/linphone.pc
share/linphone.desktop
scripts/Makefile
tools/Makefile
linphone.spec
linphone.iss
Makefile
build/Makefile
build/macos/Makefile
build/macos/Info-linphone.plist
m4/Makefile
po/Makefile.in
pixmaps/Makefile
coreapi/Makefile
coreapi/help/Makefile
coreapi/help/Doxyfile
gtk/Makefile
console/Makefile
daemon/Makefile
share/Makefile
share/C/Makefile
share/fr/Makefile
share/it/Makefile
share/ja/Makefile
share/cs/Makefile
share/xml/Makefile
share/linphone.pc
share/linphone.desktop
scripts/Makefile
tools/Makefile
linphone.spec
linphone.iss
])
AC_OUTPUT
echo "Linphone build configuration ended."
echo "Summary of build options:"
printf "* Video support\t\t\t%s\n" $video
printf "* GTK interface\t\t\t%s\n" $gtk_ui
printf "* Account assistant\t\t%s\n" $build_wizard
printf "* Console interface\t\t%s\n" $console_ui
printf "* Tools\t\t\t\t%s\n" $build_tools
printf "* zRTP encryption (GPLv3)\t%s\n" $zrtp
printf "* %-30s %s\n" "Video support" $video
printf "* %-30s %s\n" "GTK interface" $gtk_ui
printf "* %-30s %s\n" "Account assistant" $build_wizard
printf "* %-30s %s\n" "Console interface" $console_ui
printf "* %-30s %s\n" "Tools" $build_tools
printf "* %-30s %s\n" "Message storage" $enable_msg_storage
printf "* %-30s %s\n" "zRTP encryption (GPLv3)" $zrtp
printf "* %-30s %s\n" "uPnP support" $build_upnp
if test "$enable_tunnel" = "true" ; then
printf "* Tunnel support\t\ttrue\n"

View file

@ -14,6 +14,7 @@ COMMON_CFLAGS=\
$(READLINE_CFLAGS) \
$(OSIP_CFLAGS) \
$(ORTP_CFLAGS) \
$(SQLITE3_CFLAGS) \
$(MEDIASTREAMER_CFLAGS)
if BUILD_CONSOLE
@ -26,11 +27,9 @@ endif
linphonec_SOURCES=linphonec.c linphonec.h commands.c
linphonec_CFLAGS=$(COMMON_CFLAGS) $(CONSOLE_FLAGS)
linphonec_LDADD=$(top_builddir)/coreapi/liblinphone.la $(READLINE_LIBS) \
$(MEDIASTREAMER_LIBS) \
$(ORTP_LIBS) \
$(SPEEX_LIBS) \
$(OSIP_LIBS) \
linphonec_LDADD=$(top_builddir)/coreapi/liblinphone.la \
$(READLINE_LIBS) \
$(SQLITE3_LIBS) \
$(X11_LIBS)
if BUILD_WIN32

View file

@ -206,7 +206,7 @@ static LPC_COMMAND commands[] = {
{ "autoanswer", lpc_cmd_autoanswer, "Show/set auto-answer mode",
"'autoanswer' \t: show current autoanswer mode\n"
"'autoanswer enable'\t: enable autoanswer mode\n"
"'autoanswer disable'\t: disable autoanswer mode \n"},
"'autoanswer disable'\t: disable autoanswer mode<EFBFBD><EFBFBD>\n"},
{ "proxy", lpc_cmd_proxy, "Manage proxies",
"'proxy list' : list all proxy setups.\n"
"'proxy add' : add a new proxy setup.\n"
@ -244,6 +244,8 @@ static LPC_COMMAND commands[] = {
"'firewall none' : use direct connection.\n"
"'firewall nat' : use nat address given with the 'nat' command.\n"
"'firewall stun' : use stun server given with the 'stun' command.\n"
"'firewall ice' : use ice.\n"
"'firewall upnp' : use uPnP IGD.\n"
},
{ "call-logs", lpc_cmd_call_logs, "Calls history", NULL },
{ "friend", lpc_cmd_friend, "Manage friends",
@ -850,6 +852,10 @@ lpc_cmd_firewall(LinphoneCore *lc, char *args)
{
linphone_core_set_firewall_policy(lc,LinphonePolicyNoFirewall);
}
else if (strcmp(args,"upnp")==0)
{
linphone_core_set_firewall_policy(lc,LinphonePolicyUseUpnp);
}
else if (strcmp(args,"ice")==0)
{
setting = linphone_core_get_stun_server(lc);
@ -896,6 +902,9 @@ lpc_cmd_firewall(LinphoneCore *lc, char *args)
case LinphonePolicyUseIce:
linphonec_out("Using ice with stun server %s to discover firewall address\n", setting ? setting : linphone_core_get_stun_server(lc));
break;
case LinphonePolicyUseUpnp:
linphonec_out("Using uPnP IGD protocol\n");
break;
}
return 1;
}
@ -1962,7 +1971,7 @@ static int lpc_cmd_duration(LinphoneCore *lc, char *args){
for(;elem!=NULL;elem=elem->next){
if (elem->next==NULL){
cl=(LinphoneCallLog*)elem->data;
linphonec_out("%i seconds\n",cl->duration);
linphonec_out("%i seconds\n",linphone_call_log_get_duration(cl));
}
}
return 1;
@ -2501,13 +2510,15 @@ static int lpc_cmd_camera(LinphoneCore *lc, char *args){
const LinphoneCallParams *cp=linphone_call_get_current_params (call);
if (args){
linphone_call_enable_camera(call,activated);
if ((activated && !linphone_call_params_video_enabled (cp))){
/*update the call to add the video stream*/
LinphoneCallParams *ncp=linphone_call_params_copy(cp);
linphone_call_params_enable_video(ncp,TRUE);
linphone_core_update_call(lc,call,ncp);
linphone_call_params_destroy (ncp);
linphonec_out("Trying to bring up video stream...\n");
if (linphone_call_get_state(call)==LinphoneCallStreamsRunning){
if ((activated && !linphone_call_params_video_enabled (cp))){
/*update the call to add the video stream*/
LinphoneCallParams *ncp=linphone_call_params_copy(cp);
linphone_call_params_enable_video(ncp,TRUE);
linphone_core_update_call(lc,call,ncp);
linphone_call_params_destroy (ncp);
linphonec_out("Trying to bring up video stream...\n");
}
}
}
if (linphone_call_camera_enabled (call))

View file

@ -1400,6 +1400,7 @@ copy_file(const char *from, const char *to)
snprintf(message, 255, "Can't open %s for writing: %s\n",
to, strerror(errno));
fprintf(stderr, "%s", message);
fclose(in);
return 0;
}
@ -1408,6 +1409,8 @@ copy_file(const char *from, const char *to)
{
if ( ! fwrite(buf, 1, n, out) )
{
fclose(in);
fclose(out);
return 0;
}
}

View file

@ -1,6 +1,6 @@
GITVERSION_FILE=liblinphone_gitversion.h
GITVERSION_FILE_TMP=liblinphone_gitversion.h.tmp
GITDESCRIBE=`git describe`
GITDESCRIBE=`git describe --always`
GITREVISION=`git rev-parse HEAD`
ECHO=/bin/echo
@ -16,7 +16,7 @@ CLEANFILES=$(GITVERSION_FILE)
## Process this file with automake to produce Makefile.in
linphone_includedir=$(includedir)/linphone
linphone_include_HEADERS=linphonecore.h linphonefriend.h linphonecore_utils.h ../config.h lpconfig.h sipsetup.h
linphone_include_HEADERS=linphonecore.h linphonefriend.h linphonecore_utils.h lpconfig.h sipsetup.h
if BUILD_TUNNEL
linphone_include_HEADERS+=linphone_tunnel.h
@ -47,15 +47,22 @@ liblinphone_la_SOURCES=\
lsd.c linphonecore_utils.h \
ec-calibrator.c \
conference.c \
linphone_tunnel.cc \
message_storage.c \
$(GITVERSION_FILE)
if BUILD_UPNP
liblinphone_la_SOURCES+=upnp.c upnp.h
endif
if BUILD_WIZARD
liblinphone_la_SOURCES+=sipwizard.c
endif
liblinphone_la_SOURCES+=linphone_tunnel_config.c
if BUILD_TUNNEL
liblinphone_la_SOURCES+=TunnelManager.cc TunnelManager.hh
liblinphone_la_SOURCES+=linphone_tunnel.cc TunnelManager.cc TunnelManager.hh
else
liblinphone_la_SOURCES+=linphone_tunnel_stubs.c
endif
@ -67,7 +74,9 @@ liblinphone_la_LIBADD= \
$(MEDIASTREAMER_LIBS) \
$(ORTP_LIBS) $(OPENSSL_LIBS) \
$(TUNNEL_LIBS) \
$(LIBSOUP_LIBS)
$(LIBSOUP_LIBS) \
$(SQLITE3_LIBS)
if BUILD_TESTS
noinst_PROGRAMS=test_lsd test_ecc test_numbers
@ -100,7 +109,8 @@ AM_CFLAGS=\
$(IPV6_CFLAGS) \
-DORTP_INET6 \
$(VIDEO_CFLAGS) \
$(TUNNEL_CFLAGS)
$(TUNNEL_CFLAGS) \
$(SQLITE3_CFLAGS)
if BUILD_WIZARD
AM_CFLAGS+= -DBUILD_WIZARD

View file

@ -102,11 +102,19 @@ int TunnelManager::eXosipSelect(int max_fds, fd_set *s1, fd_set *s2, fd_set *s3,
void TunnelManager::addServer(const char *ip, int port,unsigned int udpMirrorPort,unsigned int delay) {
if (ip == NULL) {
ip = "";
ms_warning("Adding tunnel server with empty ip, it will not work!");
}
addServer(ip,port);
mUdpMirrorClients.push_back(UdpMirrorClient(ServerAddr(ip,udpMirrorPort),delay));
}
void TunnelManager::addServer(const char *ip, int port) {
if (ip == NULL) {
ip = "";
ms_warning("Adding tunnel server with empty ip, it will not work!");
}
mServerAddrs.push_back(ServerAddr(ip,port));
if (mTunnelClient) mTunnelClient->addServer(ip,port);
}
@ -181,7 +189,7 @@ bool TunnelManager::isStarted() {
}
bool TunnelManager::isReady() const {
return mTunnelClient && mTunnelClient->isReady();
return mTunnelClient && mTunnelClient->isReady() && mReady;
}
int TunnelManager::customSendto(struct _RtpTransport *t, mblk_t *msg , int flags, const struct sockaddr *to, socklen_t tolen){
@ -206,6 +214,7 @@ TunnelManager::TunnelManager(LinphoneCore* lc) :TunnelClientController()
,mEnabled(false)
,mTunnelClient(NULL)
,mAutoDetectStarted(false)
,mReady(false)
,mHttpProxyPort(0){
mExosipTransport.data=this;
@ -253,7 +262,7 @@ void TunnelManager::processTunnelEvent(const Event &ev){
//force transport to udp
LCSipTransports lTransport;
lTransport.udp_port=15060;
lTransport.udp_port=(0xDFFF&random())+1024;
lTransport.tcp_port=0;
lTransport.tls_port=0;
lTransport.dtls_port=0;
@ -263,6 +272,7 @@ void TunnelManager::processTunnelEvent(const Event &ev){
if (lProxy) {
linphone_proxy_config_done(lProxy);
}
mReady=true;
}else if (mEnabled && !mTunnelClient->isReady()){
/* we got disconnected from the tunnel */
if (lProxy && linphone_proxy_config_is_registered(lProxy)) {
@ -270,6 +280,7 @@ void TunnelManager::processTunnelEvent(const Event &ev){
linphone_proxy_config_edit(lProxy);
linphone_core_iterate(mCore);
}
mReady=false;
}
}
@ -309,7 +320,7 @@ void TunnelManager::enable(bool isEnable) {
mEnabled=false;
stopClient();
mReady=false;
linphone_core_set_rtp_transport_factories(mCore,NULL);
eXosip_transport_hook_register(NULL);

View file

@ -129,6 +129,7 @@ class UdpMirrorClient;
*/
LinphoneCore *getLinphoneCore();
virtual void setHttpProxy(const char *host,int port, const char *username, const char *passwd);
virtual bool isReady() const;
private:
enum EventType{
UdpMirrorClientEvent,
@ -143,7 +144,6 @@ class UdpMirrorClient;
};
typedef std::list<UdpMirrorClient> UdpMirrorClientList;
virtual bool isStarted();
virtual bool isReady() const;
void onIterate();
static int customSendto(struct _RtpTransport *t, mblk_t *msg , int flags, const struct sockaddr *to, socklen_t tolen);
static int customRecvfrom(struct _RtpTransport *t, mblk_t *msg, int flags, struct sockaddr *from, socklen_t *fromlen);
@ -173,6 +173,7 @@ class UdpMirrorClient;
Mutex mMutex;
static Mutex sMutex;
bool mAutoDetectStarted;
bool mReady;
LinphoneRtpTransportFactories mTransportFactories;
std::string mHttpUserName;
std::string mHttpPasswd;

View file

@ -80,6 +80,13 @@ const char *linphone_auth_info_get_userid(const LinphoneAuthInfo *i){
return i->userid;
}
const char *linphone_auth_info_get_realm(const LinphoneAuthInfo *i){
return i->realm;
}
const char *linphone_auth_info_get_ha1(const LinphoneAuthInfo *i){
return i->ha1;
}
/**
* Sets the password.
**/
@ -113,6 +120,27 @@ void linphone_auth_info_set_userid(LinphoneAuthInfo *info, const char *userid){
if (userid && strlen(userid)>0) info->userid=ms_strdup(userid);
}
/**
* Sets realm.
**/
void linphone_auth_info_set_realm(LinphoneAuthInfo *info, const char *realm){
if (info->realm){
ms_free(info->realm);
info->realm=NULL;
}
if (realm && strlen(realm)>0) info->realm=ms_strdup(realm);
}
/**
* Sets ha1.
**/
void linphone_auth_info_set_ha1(LinphoneAuthInfo *info, const char *ha1){
if (info->ha1){
ms_free(info->ha1);
info->ha1=NULL;
}
if (ha1 && strlen(ha1)>0) info->ha1=ms_strdup(ha1);
}
/**
* Destroys a LinphoneAuthInfo object.
**/

View file

@ -41,14 +41,14 @@ void linphone_core_update_streams_destinations(LinphoneCore *lc, LinphoneCall *c
char *rtp_addr, *rtcp_addr;
int i;
for (i = 0; i < old_md->nstreams; i++) {
for (i = 0; i < old_md->n_active_streams; i++) {
if (old_md->streams[i].type == SalAudio) {
old_audiodesc = &old_md->streams[i];
} else if (old_md->streams[i].type == SalVideo) {
old_videodesc = &old_md->streams[i];
}
}
for (i = 0; i < new_md->nstreams; i++) {
for (i = 0; i < new_md->n_active_streams; i++) {
if (new_md->streams[i].type == SalAudio) {
new_audiodesc = &new_md->streams[i];
} else if (new_md->streams[i].type == SalVideo) {
@ -151,7 +151,7 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia
bool_t send_ringbacktone=FALSE;
if (call->audiostream==NULL){
/*this happens after pausing the call locally. The streams is destroyed and then we wait the 200Ok to recreate it*/
/*this happens after pausing the call locally. The streams are destroyed and then we wait the 200Ok to recreate them*/
linphone_call_init_media_streams (call);
}
if (call->state==LinphoneCallIncomingEarlyMedia && linphone_core_get_remote_ringback_tone (lc)!=NULL){
@ -163,6 +163,9 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia
}
linphone_call_start_media_streams(call,all_muted,send_ringbacktone);
}
if (call->state==LinphoneCallPausing && call->paused_by_app && ms_list_size(lc->calls)==1){
linphone_core_play_named_tone(lc,LinphoneToneCallOnHold);
}
}
#if 0
static bool_t is_duplicate_call(LinphoneCore *lc, const LinphoneAddress *from, const LinphoneAddress *to){
@ -261,6 +264,13 @@ static void call_received(SalOp *h){
ms_message("Defer ringing to gather ICE candidates");
return;
}
#ifdef BUILD_UPNP
if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseUpnp) && (call->upnp_session != NULL)) {
/* Defer ringing until the end of the ICE candidates gathering process. */
ms_message("Defer ringing to gather uPnP candidates");
return;
}
#endif //BUILD_UPNP
linphone_core_notify_incoming_call(lc,call);
}
@ -334,9 +344,15 @@ static void call_accepted(SalOp *op){
if (call->ice_session != NULL) {
linphone_core_update_ice_from_remote_media_description(call, sal_call_get_remote_media_description(op));
}
#ifdef BUILD_UPNP
if (call->upnp_session != NULL) {
linphone_core_update_upnp_from_remote_media_description(call, sal_call_get_remote_media_description(op));
}
#endif //BUILD_UPNP
md=sal_call_get_final_media_description(op);
call->params.has_video &= linphone_core_media_description_contains_video_stream(md);
if (md)
call->params.has_video &= linphone_core_media_description_contains_video_stream(md);
if (call->state==LinphoneCallOutgoingProgress ||
call->state==LinphoneCallOutgoingRinging ||
@ -345,6 +361,7 @@ static void call_accepted(SalOp *op){
if (call->referer) linphone_core_notify_refer_state(lc,call->referer,call);
}
if (md && !sal_media_description_empty(md) && !linphone_core_incompatible_security(lc,md)){
linphone_call_update_remote_session_id_and_ver(call);
if (sal_media_description_has_dir(md,SalStreamSendOnly) ||
sal_media_description_has_dir(md,SalStreamInactive)){
if (lc->vtable.display_status){
@ -425,6 +442,13 @@ static void call_accept_update(LinphoneCore *lc, LinphoneCall *call){
linphone_core_update_ice_from_remote_media_description(call,rmd);
linphone_core_update_local_media_description_from_ice(call->localdesc,call->ice_session);
}
#ifdef BUILD_UPNP
if(call->upnp_session != NULL) {
linphone_core_update_upnp_from_remote_media_description(call, rmd);
linphone_core_update_local_media_description_from_upnp(call->localdesc,call->upnp_session);
}
#endif //BUILD_UPNP
linphone_call_update_remote_session_id_and_ver(call);
sal_call_accept(call->op);
md=sal_call_get_final_media_description(call->op);
if (md && !sal_media_description_empty(md))
@ -520,6 +544,10 @@ static void call_terminated(SalOp *op, const char *from){
if (lc->vtable.display_status!=NULL)
lc->vtable.display_status(lc,_("Call terminated."));
#ifdef BUILD_UPNP
linphone_call_delete_upnp_session(call);
#endif //BUILD_UPNP
linphone_call_set_state(call, LinphoneCallEnd,"Call ended");
}
@ -589,7 +617,7 @@ static void call_failure(SalOp *op, SalError error, SalReason sr, const char *de
if (call->state==LinphoneCallOutgoingInit || call->state==LinphoneCallOutgoingProgress){
/* clear SRTP local params */
call->params.media_encryption = LinphoneMediaEncryptionNone;
for(i=0; i<call->localdesc->nstreams; i++) {
for(i=0; i<call->localdesc->n_active_streams; i++) {
call->localdesc->streams[i].proto = SalProtoRtpAvp;
memset(call->localdesc->streams[i].crypto, 0, sizeof(call->localdesc->streams[i].crypto));
}
@ -616,12 +644,21 @@ static void call_failure(SalOp *op, SalError error, SalReason sr, const char *de
/*resume to the call that send us the refer automatically*/
linphone_core_resume_call(lc,call->referer);
}
#ifdef BUILD_UPNP
linphone_call_delete_upnp_session(call);
#endif //BUILD_UPNP
if (sr == SalReasonDeclined) {
call->reason=LinphoneReasonDeclined;
linphone_call_set_state(call,LinphoneCallEnd,"Call declined.");
} else if (sr == SalReasonNotFound) {
call->reason=LinphoneReasonNotFound;
linphone_call_set_state(call,LinphoneCallError,"User not found.");
} else if (sr == SalReasonBusy) {
call->reason=LinphoneReasonBusy;
linphone_call_set_state(call,LinphoneCallError,"User is busy.");
linphone_core_play_named_tone(lc,LinphoneToneBusy);
} else {
linphone_call_set_state(call,LinphoneCallError,msg);
}
@ -777,7 +814,7 @@ static void refer_received(Sal *sal, SalOp *op, const char *referto){
}
if (call->state!=LinphoneCallPaused){
ms_message("Automatically pausing current call to accept transfer.");
linphone_core_pause_call(lc,call);
_linphone_core_pause_call(lc,call);
call->was_automatically_paused=TRUE;
/*then we will start the refered when the pause is accepted, in order to serialize transactions within the dialog.
* Indeed we need to avoid to send a NOTIFY to inform about of state of the refered call while the pause isn't completed.
@ -810,10 +847,10 @@ static bool_t is_duplicate_msg(LinphoneCore *lc, const char *msg_id){
}
static void text_received(Sal *sal, const SalMessage *msg){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal);
static void text_received(SalOp *op, const SalMessage *msg){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
if (is_duplicate_msg(lc,msg->message_id)==FALSE){
linphone_core_message_received(lc,msg->from,msg->text,msg->url);
linphone_core_message_received(lc,op,msg);
}
}
@ -902,9 +939,11 @@ static void text_delivery_update(SalOp *op, SalTextDeliveryStatus status){
LinphoneChatMessage *chat_msg=(LinphoneChatMessage* )sal_op_get_user_pointer(op);
const MSList* calls = linphone_core_get_calls(chat_msg->chat_room->lc);
chat_msg->state=chatStatusSal2Linphone(status);
linphone_chat_message_store_state(chat_msg);
if (chat_msg && chat_msg->cb) {
chat_msg->cb(chat_msg
,chatStatusSal2Linphone(status)
,chat_msg->state
,chat_msg->cb_ud);
}
linphone_chat_message_destroy(chat_msg);

View file

@ -25,8 +25,19 @@
#include "linphonecore.h"
#include "private.h"
#include "lpconfig.h"
LinphoneChatRoom * linphone_core_create_chat_room(LinphoneCore *lc, const char *to){
/**
* @addtogroup chatroom
* @{
*/
/**
* Create a new chat room for messaging from a sip uri like sip:joe@sip.linphone.org
* @param lc #LinphoneCore object
* @param to destination address for messages
* @return #LinphoneChatRoom where messaging can take place.
*/
LinphoneChatRoom * linphone_core_create_chat_room(LinphoneCore *lc, const char *to){
LinphoneAddress *parsed_url=NULL;
if ((parsed_url=linphone_core_interpret_url(lc,to))!=NULL){
@ -38,15 +49,19 @@
return cr;
}
return NULL;
}
}
void linphone_chat_room_destroy(LinphoneChatRoom *cr){
/**
* Destroy a LinphoneChatRoom.
* @param cr #LinphoneChatRoom object
*/
void linphone_chat_room_destroy(LinphoneChatRoom *cr){
LinphoneCore *lc=cr->lc;
lc->chatrooms=ms_list_remove(lc->chatrooms,(void *) cr);
linphone_address_destroy(cr->peer_url);
ms_free(cr->peer);
}
}
static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage* msg){
@ -55,8 +70,9 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatM
SalOp *op=NULL;
LinphoneCall *call;
char* content_type;
time_t t=time(NULL);
if (lp_config_get_int(cr->lc->config,"sip","chat_use_call_dialogs",1)){
if (lp_config_get_int(cr->lc->config,"sip","chat_use_call_dialogs",0)){
if((call = linphone_core_get_call_by_remote_address(cr->lc,cr->peer))!=NULL){
if (call->state==LinphoneCallConnected ||
call->state==LinphoneCallStreamsRunning ||
@ -69,26 +85,39 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatM
}
}
}
msg->time=t;
if (op==NULL){
/*sending out of calls*/
op = sal_op_new(cr->lc->sal);
sal_op_set_route(op,route);
sal_op_set_user_pointer(op, msg); /*if out of call, directly store msg*/
if (msg->custom_headers){
sal_op_set_custom_header(op,msg->custom_headers);
msg->custom_headers=NULL; /*transfered to the SalOp*/
}
}
if (msg->external_body_url) {
content_type=ms_strdup_printf("message/external-body; access-type=URL; URL=\"%s\"",msg->external_body_url);
sal_message_send(op,identity,cr->peer,content_type,NULL);
sal_message_send(op,identity,cr->peer,content_type, NULL);
ms_free(content_type);
} else {
sal_text_send(op, identity, cr->peer, msg->message);
sal_text_send(op, identity, cr->peer,msg->message);
}
msg->dir=LinphoneChatMessageOutgoing;
msg->from=linphone_address_new(identity);
linphone_chat_message_store(msg);
}
/**
* Send a message to peer member of this chat room.
* @deprecated linphone_chat_room_send_message2() gives more control on the message expedition.
* @param cr #LinphoneChatRoom object
* @param msg message to be sent
*/
void linphone_chat_room_send_message(LinphoneChatRoom *cr, const char *msg) {
_linphone_chat_room_send_message(cr,linphone_chat_room_create_message(cr,msg));
}
bool_t linphone_chat_room_matches(LinphoneChatRoom *cr, const LinphoneAddress *from){
if (linphone_address_get_username(cr->peer_url) && linphone_address_get_username(from) &&
strcmp(linphone_address_get_username(cr->peer_url),linphone_address_get_username(from))==0) return TRUE;
@ -103,14 +132,15 @@ void linphone_chat_room_message_received(LinphoneChatRoom *cr, LinphoneCore *lc,
}
void linphone_core_message_received(LinphoneCore *lc, const char *from, const char *raw_msg,const char* external_url){
MSList *elem;
/**
* Retrieve an existing chat room whose peer is the supplied address, if exists.
* @param lc the linphone core
* @param add a linphone address.
* @returns the matching chatroom, or NULL if no such chatroom exists.
**/
LinphoneChatRoom *linphone_core_get_chat_room(LinphoneCore *lc, const LinphoneAddress *addr){
LinphoneChatRoom *cr=NULL;
LinphoneAddress *addr;
char *cleanfrom;
LinphoneChatMessage* msg;
addr=linphone_address_new(from);
linphone_address_clean(addr);
MSList *elem;
for(elem=lc->chatrooms;elem!=NULL;elem=ms_list_next(elem)){
cr=(LinphoneChatRoom*)elem->data;
if (linphone_chat_room_matches(cr,addr)){
@ -118,59 +148,114 @@ void linphone_core_message_received(LinphoneCore *lc, const char *from, const ch
}
cr=NULL;
}
return cr;
}
void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessage *sal_msg){
LinphoneChatRoom *cr=NULL;
LinphoneAddress *addr;
char *cleanfrom;
char *from;
LinphoneChatMessage* msg;
const SalCustomHeader *ch;
addr=linphone_address_new(sal_msg->from);
linphone_address_clean(addr);
cr=linphone_core_get_chat_room(lc,addr);
cleanfrom=linphone_address_as_string(addr);
from=linphone_address_as_string_uri_only(addr);
if (cr==NULL){
/* create a new chat room */
cr=linphone_core_create_chat_room(lc,cleanfrom);
}
msg = linphone_chat_room_create_message(cr, raw_msg);
msg = linphone_chat_room_create_message(cr, sal_msg->text);
linphone_chat_message_set_from(msg, cr->peer_url);
if (external_url) {
linphone_chat_message_set_external_body_url(msg, external_url);
{
LinphoneAddress *to;
to=sal_op_get_to(op) ? linphone_address_new(sal_op_get_to(op)) : linphone_address_new(linphone_core_get_identity(lc));
msg->to=to;
}
msg->time=sal_msg->time;
msg->state=LinphoneChatMessageStateDelivered;
msg->is_read=FALSE;
ch=sal_op_get_custom_header(op);
if (ch) msg->custom_headers=sal_custom_header_clone(ch);
if (sal_msg->url) {
linphone_chat_message_set_external_body_url(msg, sal_msg->url);
}
linphone_address_destroy(addr);
linphone_chat_message_store(msg);
linphone_chat_room_message_received(cr,lc,msg);
ms_free(cleanfrom);
ms_free(from);
}
/**
* Returns back pointer to LinphoneCore object.
**/
LinphoneCore* linphone_chat_room_get_lc(LinphoneChatRoom *cr){
return cr->lc;
}
LinphoneChatRoom* linphone_chat_message_get_chat_room(LinphoneChatMessage *msg){
return msg->chat_room;
}
/**
* Assign a user pointer to the chat room.
**/
void linphone_chat_room_set_user_data(LinphoneChatRoom *cr, void * ud){
cr->user_data=ud;
}
/**
* Retrieve the user pointer associated with the chat room.
**/
void * linphone_chat_room_get_user_data(LinphoneChatRoom *cr){
return cr->user_data;
}
/**
* get peer address \link linphone_core_create_chat_room() associated to \endlink this #LinphoneChatRoom
* @param cr #LinphoneChatRoom object
* @return #LinphoneAddress peer address
*/
const LinphoneAddress* linphone_chat_room_get_peer_address(LinphoneChatRoom *cr) {
return cr->peer_url;
}
LinphoneChatMessage* linphone_chat_room_create_message(const LinphoneChatRoom *cr,const char* message) {
/**
* Create a message attached to a dedicated chat room;
* @param cr the chat room.
* @param message text message, NULL if absent.
* @return a new #LinphoneChatMessage
*/
LinphoneChatMessage* linphone_chat_room_create_message(LinphoneChatRoom *cr, const char* message) {
LinphoneChatMessage* msg = ms_new0(LinphoneChatMessage,1);
msg->chat_room=(LinphoneChatRoom*)cr;
msg->message=message?ms_strdup(message):NULL;
msg->is_read=TRUE;
return msg;
}
void linphone_chat_message_destroy(LinphoneChatMessage* msg) {
if (msg->message) ms_free(msg->message);
if (msg->external_body_url) ms_free(msg->external_body_url);
if (msg->from) linphone_address_destroy(msg->from);
ms_free(msg);
}
void linphone_chat_room_send_message2(LinphoneChatRoom *cr, LinphoneChatMessage* msg,LinphoneChatMessageStateChangeCb status_cb,void* ud) {
/**
* Send a message to peer member of this chat room.
* @param cr #LinphoneChatRoom object
* @param msg #LinphoneChatMessage message to be sent
* @param status_cb LinphoneChatMessageStateChangeCb status callback invoked when message is delivered or could not be delivered. May be NULL
* @param ud user data for the status cb.
* @note The LinphoneChatMessage must not be destroyed until the the callback is called.
*/
void linphone_chat_room_send_message2(LinphoneChatRoom *cr, LinphoneChatMessage* msg,LinphoneChatMessageStateChangeCb status_cb, void* ud) {
msg->cb=status_cb;
msg->cb_ud=ud;
msg->state=LinphoneChatMessageStateInProgress;
_linphone_chat_room_send_message(cr, msg);
}
/**
* Returns a #LinphoneChatMessageState as a string.
*/
const char* linphone_chat_message_state_to_string(const LinphoneChatMessageState state) {
switch (state) {
case LinphoneChatMessageStateIdle:return "LinphoneChatMessageStateIdle";
@ -182,48 +267,143 @@ const char* linphone_chat_message_state_to_string(const LinphoneChatMessageState
}
char* linphone_chat_message_get_message(LinphoneChatMessage* msg) {
return msg->message;
/**
* Returns the chatroom this message belongs to.
**/
LinphoneChatRoom* linphone_chat_message_get_chat_room(LinphoneChatMessage *msg){
return msg->chat_room;
}
/**
* Returns the peer (remote) address for the message.
**/
const LinphoneAddress* linphone_chat_message_get_peer_address(LinphoneChatMessage *msg) {
return linphone_chat_room_get_peer_address(msg->chat_room);
}
/**
* user pointer set function
*User pointer set function
*/
void linphone_chat_message_set_user_data(LinphoneChatMessage* message,void* ud) {
message->message_userdata=ud;
}
/**
* user pointer get function
* User pointer get function
*/
void* linphone_chat_message_get_user_data(const LinphoneChatMessage* message) {
return message->message_userdata;
}
/**
* Linphone message can carry external body as defined by rfc2017
* @param message #LinphoneChatMessage
* @return external body url or NULL if not present.
*/
const char* linphone_chat_message_get_external_body_url(const LinphoneChatMessage* message) {
return message->external_body_url;
}
/**
* Linphone message can carry external body as defined by rfc2017
*
* @param message a LinphoneChatMessage
* @param url ex: access-type=URL; URL="http://www.foo.com/file"
*/
void linphone_chat_message_set_external_body_url(LinphoneChatMessage* message,const char* url) {
if (message->external_body_url) {
ms_free(message->external_body_url);
}
message->external_body_url=url?ms_strdup(url):NULL;
}
/**
* Set origin of the message
*@param message #LinphoneChatMessage obj
*@param from #LinphoneAddress origin of this message (copied)
*/
void linphone_chat_message_set_from(LinphoneChatMessage* message, const LinphoneAddress* from) {
if(message->from) linphone_address_destroy(message->from);
message->from=linphone_address_clone(from);
}
LinphoneAddress* linphone_chat_message_get_from(const LinphoneChatMessage* message) {
/**
* Get origin of the message
*@param message #LinphoneChatMessage obj
*@return #LinphoneAddress
*/
const LinphoneAddress* linphone_chat_message_get_from(const LinphoneChatMessage* message) {
return message->from;
}
/**
* Get destination of the message
*@param message #LinphoneChatMessage obj
*@return #LinphoneAddress
*/
const LinphoneAddress* linphone_chat_message_get_to(const LinphoneChatMessage* message){
if (message->to) return message->to;
if (message->dir==LinphoneChatMessageOutgoing){
return message->chat_room->peer_url;
}
return NULL;
}
/**
* Returns the origin address of a message if it was a outgoing message, or the destination address if it was an incoming message.
*@param message #LinphoneChatMessage obj
*@return #LinphoneAddress
*/
LinphoneAddress *linphone_chat_message_get_local_address(const LinphoneChatMessage* message){
return message->dir==LinphoneChatMessageOutgoing ? message->from : message->to;
}
/**
* Get the time the message was sent.
*/
time_t linphone_chat_message_get_time(const LinphoneChatMessage* message) {
return message->time;
}
/**
* Get the state of the message
*@param message #LinphoneChatMessage obj
*@return #LinphoneChatMessageState
*/
LinphoneChatMessageState linphone_chat_message_get_state(const LinphoneChatMessage* message) {
return message->state;
}
/**
* Get text part of this message
* @return text or NULL if no text.
*/
const char * linphone_chat_message_get_text(const LinphoneChatMessage* message) {
return message->message;
}
/**
* Add custom headers to the message.
* @param message the message
* @param header_name name of the header_name
* @param header_value header value
**/
void linphone_chat_message_add_custom_header(LinphoneChatMessage* message, const char *header_name, const char *header_value){
message->custom_headers=sal_custom_header_append(message->custom_headers,header_name,header_value);
}
/**
* Retrieve a custom header value given its name.
* @param message the message
* @param header_name header name searched
**/
const char * linphone_chat_message_get_custom_header(LinphoneChatMessage* message, const char *header_name){
return sal_custom_header_find(message->custom_headers,header_name);
}
/**
* Duplicate a LinphoneChatMessage
**/
LinphoneChatMessage* linphone_chat_message_clone(const LinphoneChatMessage* msg) {
/*struct _LinphoneChatMessage {
char* message;
@ -233,6 +413,9 @@ LinphoneChatMessage* linphone_chat_message_clone(const LinphoneChatMessage* msg)
void* message_userdata;
char* external_body_url;
LinphoneAddress* from;
time_t time;
SalCustomHeader *custom_headers;
LinphoneChatMessageState state;
};*/
LinphoneChatMessage* new_message = linphone_chat_room_create_message(msg->chat_room,msg->message);
if (msg->external_body_url) new_message->external_body_url=ms_strdup(msg->external_body_url);
@ -240,6 +423,27 @@ LinphoneChatMessage* linphone_chat_message_clone(const LinphoneChatMessage* msg)
new_message->cb_ud=msg->cb_ud;
new_message->message_userdata=msg->message_userdata;
new_message->cb=msg->cb;
new_message->time=msg->time;
new_message->state=msg->state;
if (msg->from) new_message->from=linphone_address_clone(msg->from);
return new_message;
}
/**
* Destroys a LinphoneChatMessage.
**/
void linphone_chat_message_destroy(LinphoneChatMessage* msg) {
if (msg->message) ms_free(msg->message);
if (msg->external_body_url) ms_free(msg->external_body_url);
if (msg->from) linphone_address_destroy(msg->from);
if (msg->to) linphone_address_destroy(msg->to);
if (msg->custom_headers) sal_custom_header_free(msg->custom_headers);
ms_free(msg);
}
/**
* @}
*/

View file

@ -55,22 +55,38 @@ static void remove_local_endpoint(LinphoneConference *ctx){
}
}
static int linphone_conference_get_size(LinphoneConference *conf){
if (conf->conf == NULL) {
return 0;
}
return ms_audio_conference_get_size(conf->conf) - (conf->record_endpoint ? 1 : 0);
}
static int remote_participants_count(LinphoneConference *ctx) {
if (!ctx->conf || ms_audio_conference_get_size(ctx->conf)==0) return 0;
if (!ctx->local_participant) return ms_audio_conference_get_size(ctx->conf);
return ms_audio_conference_get_size(ctx->conf) -1;
int count=linphone_conference_get_size(ctx);
if (count==0) return 0;
if (!ctx->local_participant) return count;
return count -1;
}
void linphone_core_conference_check_uninit(LinphoneCore *lc){
LinphoneConference *ctx=&lc->conf_ctx;
if (ctx->conf){
ms_message("conference_check_uninit(): nmembers=%i",ms_audio_conference_get_size(ctx->conf));
if (remote_participants_count(ctx)==1){
int remote_count=remote_participants_count(ctx);
ms_message("conference_check_uninit(): size=%i",linphone_conference_get_size(ctx));
if (remote_count==1){
convert_conference_to_call(lc);
}
if (ms_audio_conference_get_size(ctx->conf)==1 && ctx->local_participant!=NULL){
remove_local_endpoint(ctx);
if (remote_count==0){
if (ctx->local_participant!=NULL)
remove_local_endpoint(ctx);
if (ctx->record_endpoint){
ms_audio_conference_remove_member(ctx->conf,ctx->record_endpoint);
ms_audio_endpoint_destroy(ctx->record_endpoint);
ctx->record_endpoint=NULL;
}
}
if (ms_audio_conference_get_size(ctx->conf)==0){
ms_audio_conference_destroy(ctx->conf);
ctx->conf=NULL;
@ -161,11 +177,11 @@ float linphone_core_get_conference_local_input_volume(LinphoneCore *lc){
*
* If this is the first call that enters the conference, the virtual conference will be created automatically.
* If the local user was actively part of the call (ie not in paused state), then the local user is automatically entered into the conference.
* If the call was in paused state, then it is automatically resumed when entering into the conference.
*
* @returns 0 if successful, -1 otherwise.
**/
int linphone_core_add_to_conference(LinphoneCore *lc, LinphoneCall *call){
LinphoneCallParams params;
LinphoneConference *conf=&lc->conf_ctx;
if (call->current_params.in_conference){
@ -173,21 +189,25 @@ int linphone_core_add_to_conference(LinphoneCore *lc, LinphoneCall *call){
return -1;
}
conference_check_init(&lc->conf_ctx, lp_config_get_int(lc->config, "sound","conference_rate",16000));
call->params.in_conference=TRUE;
call->params.has_video=FALSE;
call->params.media_encryption=LinphoneMediaEncryptionNone;
params=call->params;
if (call->state==LinphoneCallPaused)
if (call->state==LinphoneCallPaused){
call->params.in_conference=TRUE;
call->params.has_video=FALSE;
linphone_core_resume_call(lc,call);
else if (call->state==LinphoneCallStreamsRunning){
/*this will trigger a reINVITE that will later redraw the streams */
}else if (call->state==LinphoneCallStreamsRunning){
LinphoneCallParams *params=linphone_call_params_copy(linphone_call_get_current_params(call));
params->in_conference=TRUE;
params->has_video=FALSE;
if (call->audiostream || call->videostream){
linphone_call_stop_media_streams (call); /*free the audio & video local resources*/
}
if (call==lc->current_call){
lc->current_call=NULL;
}
linphone_core_update_call(lc,call,&params);
/*this will trigger a reINVITE that will later redraw the streams */
linphone_core_update_call(lc,call,params);
linphone_call_params_destroy(params);
add_local_endpoint(conf,lc);
}else{
ms_error("Call is in state %s, it cannot be added to the conference.",linphone_call_state_to_string(call->state));
@ -214,16 +234,19 @@ static int remove_from_conference(LinphoneCore *lc, LinphoneCall *call, bool_t a
ms_message("%s will be removed from conference", str);
ms_free(str);
if (active){
LinphoneCallParams *params=linphone_call_params_copy(linphone_call_get_current_params(call));
params->in_conference=FALSE;
// reconnect local audio with this call
if (linphone_core_is_in_conference(lc)){
ms_message("Leaving conference for reconnecting with unique call.");
linphone_core_leave_conference(lc);
}
ms_message("Updating call to actually remove from conference");
err=linphone_core_update_call(lc,call,&call->params);
err=linphone_core_update_call(lc,call,params);
linphone_call_params_destroy(params);
} else{
ms_message("Pausing call to actually remove from conference");
err=linphone_core_pause_call(lc,call);
err=_linphone_core_pause_call(lc,call);
}
return err;
@ -256,10 +279,13 @@ static int convert_conference_to_call(LinphoneCore *lc){
* @param call a call that has been previously merged into the conference.
*
* After removing the remote participant belonging to the supplied call, the call becomes a normal call in paused state.
* If one single remote participant is left alone in the conference after the removal, then it is
* automatically removed from the conference and put into a simple call, like before entering the conference.
* If one single remote participant is left alone together with the local user in the conference after the removal, then the conference is
* automatically transformed into a simple call in StreamsRunning state.
* The conference's resources are then automatically destroyed.
*
* In other words, unless linphone_core_leave_conference() is explicitely called, the last remote participant of a conference is automatically
* put in a simple call in running state.
*
* @returns 0 if successful, -1 otherwise.
**/
int linphone_core_remove_from_conference(LinphoneCore *lc, LinphoneCall *call){
@ -319,7 +345,7 @@ int linphone_core_enter_conference(LinphoneCore *lc){
return -1;
}
if (lc->current_call != NULL) {
linphone_core_pause_call(lc, lc->current_call);
_linphone_core_pause_call(lc, lc->current_call);
}
LinphoneConference *conf=&lc->conf_ctx;
if (conf->local_participant==NULL) add_local_endpoint(conf,lc);
@ -377,10 +403,37 @@ int linphone_core_terminate_conference(LinphoneCore *lc) {
* @returns the number of participants to the conference
**/
int linphone_core_get_conference_size(LinphoneCore *lc) {
if (lc->conf_ctx.conf == NULL) {
return 0;
LinphoneConference *conf=&lc->conf_ctx;
return linphone_conference_get_size(conf);
}
int linphone_core_start_conference_recording(LinphoneCore *lc, const char *path){
LinphoneConference *conf=&lc->conf_ctx;
if (conf->conf == NULL) {
ms_warning("linphone_core_start_conference_recording(): no conference now.");
return -1;
}
return ms_audio_conference_get_size(lc->conf_ctx.conf);
if (conf->record_endpoint==NULL){
conf->record_endpoint=ms_audio_endpoint_new_recorder();
ms_audio_conference_add_member(conf->conf,conf->record_endpoint);
}
ms_audio_recorder_endpoint_start(conf->record_endpoint,path);
return 0;
}
int linphone_core_stop_conference_recording(LinphoneCore *lc){
LinphoneConference *conf=&lc->conf_ctx;
if (conf->conf == NULL) {
ms_warning("linphone_core_stop_conference_recording(): no conference now.");
return -1;
}
if (conf->record_endpoint==NULL){
ms_warning("linphone_core_stop_conference_recording(): no record active.");
return -1;
}
ms_audio_recorder_endpoint_stop(conf->record_endpoint);
return 0;
}
/**

View file

@ -29,37 +29,47 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
static void ecc_init_filters(EcCalibrator *ecc){
unsigned int rate;
int channels = 1;
int ecc_channels = 1;
MSTickerParams params={0};
params.name="Echo calibrator";
params.prio=MS_TICKER_PRIO_HIGH;
ecc->ticker=ms_ticker_new_with_params(&params);
ecc->sndread=ms_snd_card_create_reader(ecc->play_card);
ecc->sndread=ms_snd_card_create_reader(ecc->capt_card);
ms_filter_call_method(ecc->sndread,MS_FILTER_SET_SAMPLE_RATE,&ecc->rate);
ms_filter_call_method(ecc->sndread,MS_FILTER_GET_SAMPLE_RATE,&rate);
ms_filter_call_method(ecc->sndread,MS_FILTER_SET_NCHANNELS,&ecc_channels);
ms_filter_call_method(ecc->sndread,MS_FILTER_GET_NCHANNELS,&channels);
ecc->read_resampler=ms_filter_new(MS_RESAMPLE_ID);
ms_filter_call_method(ecc->read_resampler,MS_FILTER_SET_SAMPLE_RATE,&rate);
ms_filter_call_method(ecc->read_resampler,MS_FILTER_SET_OUTPUT_SAMPLE_RATE,&ecc->rate);
ms_filter_call_method(ecc->read_resampler,MS_FILTER_SET_NCHANNELS,&ecc_channels);
ms_filter_call_method(ecc->read_resampler,MS_FILTER_SET_OUTPUT_NCHANNELS,&channels);
ecc->det=ms_filter_new(MS_TONE_DETECTOR_ID);
ms_filter_call_method(ecc->det,MS_FILTER_SET_SAMPLE_RATE,&ecc->rate);
ecc->rec=ms_filter_new(MS_FILE_REC_ID);
ecc->rec=ms_filter_new(MS_VOID_SINK_ID);
ms_filter_link(ecc->sndread,0,ecc->read_resampler,0);
ms_filter_link(ecc->read_resampler,0,ecc->det,0);
ms_filter_link(ecc->det,0,ecc->rec,0);
ecc->play=ms_filter_new(MS_FILE_PLAYER_ID);
ecc->play=ms_filter_new(MS_VOID_SOURCE_ID);
ecc->gen=ms_filter_new(MS_DTMF_GEN_ID);
ms_filter_call_method(ecc->gen,MS_FILTER_SET_SAMPLE_RATE,&ecc->rate);
ecc->write_resampler=ms_filter_new(MS_RESAMPLE_ID);
ecc->sndwrite=ms_snd_card_create_writer(ecc->capt_card);
ecc->sndwrite=ms_snd_card_create_writer(ecc->play_card);
ms_filter_call_method(ecc->sndwrite,MS_FILTER_SET_SAMPLE_RATE,&ecc->rate);
ms_filter_call_method(ecc->sndwrite,MS_FILTER_GET_SAMPLE_RATE,&rate);
ms_filter_call_method(ecc->sndwrite,MS_FILTER_SET_NCHANNELS,&ecc_channels);
ms_filter_call_method(ecc->sndwrite,MS_FILTER_GET_NCHANNELS,&channels);
ms_filter_call_method(ecc->write_resampler,MS_FILTER_SET_SAMPLE_RATE,&ecc->rate);
ms_filter_call_method(ecc->write_resampler,MS_FILTER_SET_OUTPUT_SAMPLE_RATE,&rate);
ms_filter_call_method(ecc->write_resampler,MS_FILTER_SET_NCHANNELS,&ecc_channels);
ms_filter_call_method(ecc->write_resampler,MS_FILTER_SET_OUTPUT_NCHANNELS,&channels);
ms_filter_link(ecc->play,0,ecc->gen,0);
ms_filter_link(ecc->gen,0,ecc->write_resampler,0);
@ -67,10 +77,17 @@ static void ecc_init_filters(EcCalibrator *ecc){
ms_ticker_attach(ecc->ticker,ecc->sndread);
ms_ticker_attach(ecc->ticker,ecc->play);
if (ecc->audio_init_cb != NULL) {
(*ecc->audio_init_cb)(ecc->cb_data);
}
}
static void ecc_deinit_filters(EcCalibrator *ecc){
if (ecc->audio_uninit_cb != NULL) {
(*ecc->audio_uninit_cb)(ecc->cb_data);
}
ms_ticker_detach(ecc->ticker,ecc->sndread);
ms_ticker_detach(ecc->ticker,ecc->play);
@ -97,72 +114,118 @@ static void ecc_deinit_filters(EcCalibrator *ecc){
static void on_tone_sent(void *data, MSFilter *f, unsigned int event_id, void *arg){
MSDtmfGenEvent *ev=(MSDtmfGenEvent*)arg;
EcCalibrator *ecc=(EcCalibrator*)data;
ecc->sent_count++;
ecc->acc-=ev->tone_start_time;
ms_message("Sent tone at %u",(unsigned int)ev->tone_start_time);
}
static bool_t is_valid_tone(EcCalibrator *ecc, MSToneDetectorEvent *ev){
bool_t *toneflag=NULL;
if (strcmp(ev->tone_name,"freq1")==0){
toneflag=&ecc->freq1;
}else if (strcmp(ev->tone_name,"freq2")==0){
toneflag=&ecc->freq2;
}else if (strcmp(ev->tone_name,"freq3")==0){
toneflag=&ecc->freq3;
}else{
ms_error("Calibrator bug.");
return FALSE;
}
if (*toneflag){
ms_message("Duplicated tone event, ignored.");
return FALSE;
}
*toneflag=TRUE;
return TRUE;
}
static void on_tone_received(void *data, MSFilter *f, unsigned int event_id, void *arg){
MSToneDetectorEvent *ev=(MSToneDetectorEvent*)arg;
EcCalibrator *ecc=(EcCalibrator*)data;
ecc->recv_count++;
ecc->acc+=ev->tone_start_time;
ms_message("Received tone at %u",(unsigned int)ev->tone_start_time);
if (is_valid_tone(ecc,ev)){
ecc->acc+=ev->tone_start_time;
ms_message("Received tone at %u",(unsigned int)ev->tone_start_time);
}
}
static void ecc_play_tones(EcCalibrator *ecc){
MSDtmfGenCustomTone tone;
MSToneDetectorDef expected_tone;
memset(&tone,0,sizeof(tone));
memset(&expected_tone,0,sizeof(expected_tone));
ms_filter_set_notify_callback(ecc->det,on_tone_received,ecc);
/* configure the tones to be scanned */
strncpy(expected_tone.tone_name,"freq1",sizeof(expected_tone.tone_name));
expected_tone.frequency=2000;
expected_tone.min_duration=40;
expected_tone.min_amplitude=0.02;
expected_tone.min_amplitude=0.1;
ms_filter_call_method (ecc->det,MS_TONE_DETECTOR_ADD_SCAN,&expected_tone);
tone.frequency=1300;
tone.duration=1000;
tone.amplitude=1.0;
strncpy(expected_tone.tone_name,"freq2",sizeof(expected_tone.tone_name));
expected_tone.frequency=2300;
expected_tone.min_duration=40;
expected_tone.min_amplitude=0.1;
ms_filter_call_method (ecc->det,MS_TONE_DETECTOR_ADD_SCAN,&expected_tone);
strncpy(expected_tone.tone_name,"freq3",sizeof(expected_tone.tone_name));
expected_tone.frequency=2500;
expected_tone.min_duration=40;
expected_tone.min_amplitude=0.1;
ms_filter_call_method (ecc->det,MS_TONE_DETECTOR_ADD_SCAN,&expected_tone);
/*play an initial tone to startup the audio playback/capture*/
tone.frequencies[0]=140;
tone.duration=1000;
tone.amplitude=0.5;
ms_filter_call_method(ecc->gen,MS_DTMF_GEN_PLAY_CUSTOM,&tone);
ms_sleep(2);
ms_filter_set_notify_callback(ecc->gen,on_tone_sent,ecc);
tone.frequency=2000;
/* play the three tones*/
tone.frequencies[0]=2000;
tone.duration=100;
ms_filter_call_method(ecc->gen,MS_DTMF_GEN_PLAY_CUSTOM,&tone);
ms_usleep(300000);
tone.frequencies[0]=2300;
tone.duration=100;
ms_filter_call_method(ecc->gen,MS_DTMF_GEN_PLAY_CUSTOM,&tone);
ms_usleep(300000);
tone.frequencies[0]=2500;
tone.duration=100;
ms_filter_call_method(ecc->gen,MS_DTMF_GEN_PLAY_CUSTOM,&tone);
ms_sleep(1);
ms_filter_call_method(ecc->gen,MS_DTMF_GEN_PLAY_CUSTOM,&tone);
ms_sleep(1);
ms_filter_call_method(ecc->gen,MS_DTMF_GEN_PLAY_CUSTOM,&tone);
ms_sleep(1);
if (ecc->sent_count==3) {
if (ecc->recv_count==3){
int delay=ecc->acc/3;
if (delay<0){
ms_error("Quite surprising calibration result, delay=%i",delay);
ecc->status=LinphoneEcCalibratorFailed;
}else{
ms_message("Echo calibration estimated delay to be %i ms",delay);
ecc->delay=delay;
ecc->status=LinphoneEcCalibratorDone;
}
} else if (ecc->recv_count == 0) {
if (ecc->freq1 && ecc->freq2 && ecc->freq3) {
int delay=ecc->acc/3;
if (delay<0){
ms_error("Quite surprising calibration result, delay=%i",delay);
ecc->status=LinphoneEcCalibratorFailed;
}else{
ms_message("Echo calibration estimated delay to be %i ms",delay);
ecc->delay=delay;
ecc->status=LinphoneEcCalibratorDone;
}
} else if ((ecc->freq1 || ecc->freq2 || ecc->freq3)==FALSE) {
ms_message("Echo calibration succeeded, no echo has been detected");
ecc->status = LinphoneEcCalibratorDoneNoEcho;
} else {
} else {
ecc->status = LinphoneEcCalibratorFailed;
}
}else{
ecc->status=LinphoneEcCalibratorFailed;
}
if (ecc->status == LinphoneEcCalibratorFailed) {
ms_error("Echo calibration failed, tones received = %i",ecc->recv_count);
ms_error("Echo calibration failed.");
}
}
@ -176,12 +239,15 @@ static void * ecc_thread(void *p){
return NULL;
}
EcCalibrator * ec_calibrator_new(MSSndCard *play_card, MSSndCard *capt_card, unsigned int rate, LinphoneEcCalibrationCallback cb, void *cb_data ){
EcCalibrator * ec_calibrator_new(MSSndCard *play_card, MSSndCard *capt_card, unsigned int rate, LinphoneEcCalibrationCallback cb,
LinphoneEcCalibrationAudioInit audio_init_cb, LinphoneEcCalibrationAudioUninit audio_uninit_cb, void *cb_data){
EcCalibrator *ecc=ms_new0(EcCalibrator,1);
ecc->rate=rate;
ecc->cb=cb;
ecc->cb_data=cb_data;
ecc->audio_init_cb=audio_init_cb;
ecc->audio_uninit_cb=audio_uninit_cb;
ecc->capt_card=capt_card;
ecc->play_card=play_card;
ms_thread_create(&ecc->thread,NULL,ecc_thread,ecc);
@ -197,13 +263,14 @@ void ec_calibrator_destroy(EcCalibrator *ecc){
ms_free(ecc);
}
int linphone_core_start_echo_calibration(LinphoneCore *lc, LinphoneEcCalibrationCallback cb, void *cb_data){
int linphone_core_start_echo_calibration(LinphoneCore *lc, LinphoneEcCalibrationCallback cb,
LinphoneEcCalibrationAudioInit audio_init_cb, LinphoneEcCalibrationAudioUninit audio_uninit_cb, void *cb_data){
if (lc->ecc!=NULL){
ms_error("Echo calibration is still on going !");
return -1;
}
unsigned int rate = lp_config_get_int(lc->config,"sound","echo_cancellation_rate",8000);
lc->ecc=ec_calibrator_new(lc->sound_conf.play_sndcard,lc->sound_conf.capt_sndcard,rate,cb,cb_data);
lc->ecc=ec_calibrator_new(lc->sound_conf.play_sndcard,lc->sound_conf.capt_sndcard,rate,cb,audio_init_cb,audio_uninit_cb,cb_data);
return 0;
}

View file

@ -154,13 +154,13 @@ public class TutorialChatRoom implements LinphoneCoreListener, LinphoneChatMessa
@Override
public void messageReceived(LinphoneCore lc, LinphoneChatRoom cr,
LinphoneChatMessage message) {
write("Message [" + message.getMessage() + "] received from [" + message.getFrom().asString() + "]");
write("Message [" + message.getText() + "] received from [" + message.getFrom().asString() + "]");
}
@Override
public void onLinphoneChatMessageStateChanged(LinphoneChatMessage msg,
org.linphone.core.LinphoneChatMessage.State state) {
write("Sent message [" + msg.getMessage() + "] new state is " + state.toString());
write("Sent message [" + msg.getText() + "] new state is " + state.toString());
}

View file

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

View file

@ -68,7 +68,7 @@ void linphone_tunnel_config_set_host(LinphoneTunnelConfig *tunnel, const char *h
*
* @param tunnel configuration object
*/
const char *linphone_tunnel_config_get_host(LinphoneTunnelConfig *tunnel);
const char *linphone_tunnel_config_get_host(const LinphoneTunnelConfig *tunnel);
/**
* Set tls port of server.
@ -83,7 +83,7 @@ void linphone_tunnel_config_set_port(LinphoneTunnelConfig *tunnel, int port);
*
* @param tunnel configuration object
*/
int linphone_tunnel_config_get_port(LinphoneTunnelConfig *tunnel);
int linphone_tunnel_config_get_port(const LinphoneTunnelConfig *tunnel);
/**
* Set the remote port on the tunnel server side used to test udp reachability.
@ -98,7 +98,7 @@ void linphone_tunnel_config_set_remote_udp_mirror_port(LinphoneTunnelConfig *tun
*
* @param tunnel configuration object
*/
int linphone_tunnel_config_get_remote_udp_mirror_port(LinphoneTunnelConfig *tunnel);
int linphone_tunnel_config_get_remote_udp_mirror_port(const LinphoneTunnelConfig *tunnel);
/**
* Set the udp packet round trip delay in ms for a tunnel configuration.
@ -113,7 +113,7 @@ void linphone_tunnel_config_set_delay(LinphoneTunnelConfig *tunnel, int delay);
*
* @param tunnel configuration object
*/
int linphone_tunnel_config_get_delay(LinphoneTunnelConfig *tunnel);
int linphone_tunnel_config_get_delay(const LinphoneTunnelConfig *tunnel);
/**
* Destroy a tunnel configuration
@ -165,6 +165,12 @@ void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled);
**/
bool_t linphone_tunnel_enabled(LinphoneTunnel *tunnel);
/**
* @param tunnel object
* Returns a boolean indicating whether tunnel is connected successfully.
**/
bool_t linphone_tunnel_connected(LinphoneTunnel *tunnel);
/**
* @param tunnel object
* Forces reconnection to the tunnel server.

View file

@ -0,0 +1,83 @@
/***************************************************************************
* linphone_tunnel_config.c
*
* Copyright 2012 Belledonne Communications
****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "linphone_tunnel.h"
struct _LinphoneTunnelConfig {
char *host;
int port;
int remote_udp_mirror_port;
int delay;
};
LinphoneTunnelConfig *linphone_tunnel_config_new() {
LinphoneTunnelConfig *ltc = ms_new0(LinphoneTunnelConfig,1);
ltc->remote_udp_mirror_port = 12345;
ltc->delay = 1000;
return ltc;
}
void linphone_tunnel_config_set_host(LinphoneTunnelConfig *tunnel, const char *host) {
if(tunnel->host != NULL) {
ms_free(tunnel->host);
tunnel->host = NULL;
}
if(host != NULL && strlen(host)) {
tunnel->host = ms_strdup(host);
}
}
const char *linphone_tunnel_config_get_host(const LinphoneTunnelConfig *tunnel) {
return tunnel->host;
}
void linphone_tunnel_config_set_port(LinphoneTunnelConfig *tunnel, int port) {
tunnel->port = port;
}
int linphone_tunnel_config_get_port(const LinphoneTunnelConfig *tunnel) {
return tunnel->port;
}
void linphone_tunnel_config_set_remote_udp_mirror_port(LinphoneTunnelConfig *tunnel, int remote_udp_mirror_port) {
tunnel->remote_udp_mirror_port = remote_udp_mirror_port;
}
int linphone_tunnel_config_get_remote_udp_mirror_port(const LinphoneTunnelConfig *tunnel) {
return tunnel->remote_udp_mirror_port;
}
void linphone_tunnel_config_set_delay(LinphoneTunnelConfig *tunnel, int delay) {
tunnel->delay = delay;
}
int linphone_tunnel_config_get_delay(const LinphoneTunnelConfig *tunnel) {
return tunnel->delay;
}
void linphone_tunnel_config_destroy(LinphoneTunnelConfig *tunnel) {
if(tunnel->host != NULL) {
ms_free(tunnel->host);
}
ms_free(tunnel);
}

View file

@ -0,0 +1,87 @@
/***************************************************************************
* linphone_tunnel.cc
*
* Fri Dec 9, 2011
* Copyright 2011 Belledonne Communications
* Author: Guillaume Beraudo
* Email: guillaume dot beraudo at linphone dot org
****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "linphone_tunnel.h"
#include "linphonecore.h"
#include "private.h"
#include "lpconfig.h"
LinphoneTunnel* linphone_core_get_tunnel(LinphoneCore *lc){
return lc->tunnel;
}
/*stubs to avoid to have #ifdef TUNNEL_ENABLED in upper layers*/
void linphone_tunnel_destroy(LinphoneTunnel *tunnel){
}
void linphone_tunnel_add_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config){
}
void linphone_tunnel_remove_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config){
}
const MSList *linphone_tunnel_get_servers(LinphoneTunnel *tunnel){
return NULL;
}
void linphone_tunnel_clean_servers(LinphoneTunnel *tunnel){
}
void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled){
}
bool_t linphone_tunnel_enabled(LinphoneTunnel *tunnel){
return FALSE;
}
bool_t linphone_tunnel_connected(LinphoneTunnel *tunnel){
return FALSE;
}
void linphone_tunnel_enable_logs_with_handler(LinphoneTunnel *tunnel, bool_t enabled, OrtpLogFunc logHandler){
}
void linphone_tunnel_set_http_proxy_auth_info(LinphoneTunnel *tunnel, const char* username,const char* passwd){
}
void linphone_tunnel_set_http_proxy(LinphoneTunnel*tunnel, const char *host, int port, const char* username,const char* passwd){
}
void linphone_tunnel_get_http_proxy(LinphoneTunnel*tunnel,const char **host, int *port, const char **username, const char **passwd){
}
void linphone_tunnel_reconnect(LinphoneTunnel *tunnel){
}
void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel){
}
void linphone_tunnel_configure(LinphoneTunnel *tunnel){
}

View file

@ -84,9 +84,11 @@ static bool_t linphone_call_are_all_streams_encrypted(LinphoneCall *call) {
#ifdef VIDEO_ENABLED
// If video enabled, check ZRTP encryption in videostream
const LinphoneCallParams *params=linphone_call_get_current_params(call);
if (params->has_video && !call->videostream_encrypted) {
return FALSE;
{
const LinphoneCallParams *params=linphone_call_get_current_params(call);
if (params->has_video && !call->videostream_encrypted) {
return FALSE;
}
}
#endif
@ -110,9 +112,9 @@ void propagate_encryption_changed(LinphoneCall *call){
#ifdef VIDEO_ENABLED
static void linphone_call_videostream_encryption_changed(void *data, bool_t encrypted){
ms_message("Video stream is %s", encrypted ? "encrypted" : "not encrypted");
LinphoneCall *call = (LinphoneCall *)data;
ms_message("Video stream is %s", encrypted ? "encrypted" : "not encrypted");
call->videostream_encrypted=encrypted;
propagate_encryption_changed(call);
}
@ -135,12 +137,14 @@ static void linphone_call_audiostream_encryption_changed(void *data, bool_t encr
#ifdef VIDEO_ENABLED
// Enable video encryption
const LinphoneCallParams *params=linphone_call_get_current_params(call);
if (params->has_video) {
ms_message("Trying to enable encryption on video stream");
OrtpZrtpParams params;
params.zid_file=NULL; //unused
video_stream_enable_zrtp(call->videostream,call->audiostream,&params);
{
const LinphoneCallParams *params=linphone_call_get_current_params(call);
if (params->has_video) {
OrtpZrtpParams params;
ms_message("Trying to enable encryption on video stream");
params.zid_file=NULL; //unused
video_stream_enable_zrtp(call->videostream,call->audiostream,&params);
}
}
#endif
}
@ -173,9 +177,10 @@ void linphone_call_set_authentication_token_verified(LinphoneCall *call, bool_t
propagate_encryption_changed(call);
}
static MSList *make_codec_list(LinphoneCore *lc, const MSList *codecs, int bandwidth_limit,int* max_sample_rate){
static MSList *make_codec_list(LinphoneCore *lc, const MSList *codecs, int bandwidth_limit,int* max_sample_rate, int nb_codecs_limit){
MSList *l=NULL;
const MSList *it;
int nb = 0;
if (max_sample_rate) *max_sample_rate=0;
for(it=codecs;it!=NULL;it=it->next){
PayloadType *pt=(PayloadType*)it->data;
@ -186,26 +191,30 @@ static MSList *make_codec_list(LinphoneCore *lc, const MSList *codecs, int bandw
}
if (linphone_core_check_payload_type_usability(lc,pt)){
l=ms_list_append(l,payload_type_clone(pt));
nb++;
if (max_sample_rate && payload_type_get_rate(pt)>*max_sample_rate) *max_sample_rate=payload_type_get_rate(pt);
}
}
if ((nb_codecs_limit > 0) && (nb >= nb_codecs_limit)) break;
}
return l;
}
static void update_media_description_from_stun(SalMediaDescription *md, const StunCandidate *ac, const StunCandidate *vc){
if (ac->port!=0){
strcpy(md->streams[0].rtp_addr,ac->addr);
md->streams[0].rtp_port=ac->port;
if ((ac->addr[0]!='\0' && vc->addr[0]!='\0' && strcmp(ac->addr,vc->addr)==0) || md->nstreams==1){
strcpy(md->addr,ac->addr);
int i;
for (i = 0; i < md->n_active_streams; i++) {
if ((md->streams[i].type == SalAudio) && (ac->port != 0)) {
strcpy(md->streams[0].rtp_addr,ac->addr);
md->streams[0].rtp_port=ac->port;
if ((ac->addr[0]!='\0' && vc->addr[0]!='\0' && strcmp(ac->addr,vc->addr)==0) || md->n_active_streams==1){
strcpy(md->addr,ac->addr);
}
}
if ((md->streams[i].type == SalVideo) && (vc->port != 0)) {
strcpy(md->streams[1].rtp_addr,vc->addr);
md->streams[1].rtp_port=vc->port;
}
}
if (vc->port!=0){
strcpy(md->streams[1].rtp_addr,vc->addr);
md->streams[1].rtp_port=vc->port;
}
}
void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *call){
@ -218,12 +227,13 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
const char *username=linphone_address_get_username (addr);
SalMediaDescription *md=sal_media_description_new();
bool_t keep_srtp_keys=lp_config_get_int(lc->config,"sip","keep_srtp_keys",0);
linphone_core_adapt_to_network(lc,call->ping_time,&call->params);
md->session_id=(old_md ? old_md->session_id : (rand() & 0xfff));
md->session_ver=(old_md ? (old_md->session_ver+1) : (rand() & 0xfff));
md->nstreams=1;
md->n_total_streams=(old_md ? old_md->n_total_streams : 1);
md->n_active_streams=1;
strncpy(md->addr,call->localip,sizeof(md->addr));
strncpy(md->username,username,sizeof(md->username));
@ -243,22 +253,35 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
md->streams[0].ptime=call->params.down_ptime;
else
md->streams[0].ptime=linphone_core_get_download_ptime(lc);
l=make_codec_list(lc,lc->codecs_conf.audio_codecs,call->params.audio_bw,&md->streams[0].max_rate);
l=make_codec_list(lc,lc->codecs_conf.audio_codecs,call->params.audio_bw,&md->streams[0].max_rate,-1);
pt=payload_type_clone(rtp_profile_get_payload_from_mime(lc->default_profile,"telephone-event"));
l=ms_list_append(l,pt);
md->streams[0].payloads=l;
if (call->params.has_video){
md->nstreams++;
md->n_active_streams++;
md->streams[1].rtp_port=call->video_port;
md->streams[1].rtcp_port=call->video_port+1;
md->streams[1].proto=md->streams[0].proto;
md->streams[1].type=SalVideo;
l=make_codec_list(lc,lc->codecs_conf.video_codecs,0,NULL);
l=make_codec_list(lc,lc->codecs_conf.video_codecs,0,NULL,-1);
md->streams[1].payloads=l;
}
for(i=0; i<md->nstreams; i++) {
if (md->n_total_streams < md->n_active_streams)
md->n_total_streams = md->n_active_streams;
/* Deactivate inactive streams. */
for (i = md->n_active_streams; i < md->n_total_streams; i++) {
md->streams[i].rtp_port = 0;
md->streams[i].rtcp_port = 0;
md->streams[i].proto = SalProtoRtpAvp;
md->streams[i].type = old_md->streams[i].type;
md->streams[i].dir = SalStreamInactive;
l = make_codec_list(lc, lc->codecs_conf.video_codecs, 0, NULL, 1);
md->streams[i].payloads = l;
}
for(i=0; i<md->n_active_streams; i++) {
if (md->streams[i].proto == SalProtoRtpSavp) {
if (keep_srtp_keys && old_md && old_md->streams[i].proto==SalProtoRtpSavp){
int j;
@ -283,6 +306,12 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *
linphone_core_update_local_media_description_from_ice(md, call->ice_session);
linphone_core_update_ice_state_in_call_stats(call);
}
#ifdef BUILD_UPNP
if(call->upnp_session != NULL) {
linphone_core_update_local_media_description_from_upnp(md, call->upnp_session);
linphone_core_update_upnp_state_in_call_stats(call);
}
#endif //BUILD_UPNP
linphone_address_destroy(addr);
call->localdesc=md;
if (old_md) sal_media_description_unref(old_md);
@ -416,6 +445,11 @@ void linphone_call_init_stats(LinphoneCallStats *stats, int type) {
stats->received_rtcp = NULL;
stats->sent_rtcp = NULL;
stats->ice_state = LinphoneIceStateNotActivated;
#ifdef BUILD_UPNP
stats->upnp_state = LinphoneUpnpStateIdle;
#else
stats->upnp_state = LinphoneUpnpStateNotAvailable;
#endif //BUILD_UPNP
}
@ -439,9 +473,12 @@ LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddr
call->op=sal_op_new(lc->sal);
sal_op_set_user_pointer(call->op,call);
call->core=lc;
linphone_core_get_local_ip(lc,linphone_address_get_domain(to),call->localip);
linphone_core_get_local_ip(lc,NULL,call->localip);
linphone_call_init_common(call,from,to);
call->params=*params;
_linphone_call_params_copy(&call->params,params);
sal_op_set_custom_header(call->op,call->params.custom_headers);
call->params.custom_headers=NULL;
if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) {
call->ice_session = ice_session_new();
ice_session_set_role(call->ice_session, IR_Controlling);
@ -449,6 +486,13 @@ LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddr
if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseStun) {
call->ping_time=linphone_core_run_stun_tests(call->core,call);
}
#ifdef BUILD_UPNP
if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseUpnp) {
if(!lc->rtp_conf.disable_upnp) {
call->upnp_session = linphone_upnp_session_new(call);
}
}
#endif //BUILD_UPNP
call->camera_active=params->has_video;
discover_mtu(lc,linphone_address_get_domain (to));
@ -470,18 +514,25 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro
call->core=lc;
if (lc->sip_conf.ping_with_options){
/*the following sends an option request back to the caller so that
we get a chance to discover our nat'd address before answering.*/
call->ping_op=sal_op_new(lc->sal);
from_str=linphone_address_as_string_uri_only(from);
sal_op_set_route(call->ping_op,sal_op_get_network_origin(op));
sal_op_set_user_pointer(call->ping_op,call);
sal_ping(call->ping_op,linphone_core_find_best_identity(lc,from,NULL),from_str);
ms_free(from_str);
#ifdef BUILD_UPNP
if (lc->upnp != NULL && linphone_core_get_firewall_policy(lc)==LinphonePolicyUseUpnp &&
linphone_upnp_context_get_state(lc->upnp) == LinphoneUpnpStateOk) {
#else //BUILD_UPNP
{
#endif //BUILD_UPNP
/*the following sends an option request back to the caller so that
we get a chance to discover our nat'd address before answering.*/
call->ping_op=sal_op_new(lc->sal);
from_str=linphone_address_as_string_uri_only(from);
sal_op_set_route(call->ping_op,sal_op_get_network_origin(op));
sal_op_set_user_pointer(call->ping_op,call);
sal_ping(call->ping_op,linphone_core_find_best_identity(lc,from,NULL),from_str);
ms_free(from_str);
}
}
linphone_address_clean(from);
linphone_core_get_local_ip(lc,linphone_address_get_domain(from),call->localip);
linphone_core_get_local_ip(lc,NULL,call->localip);
linphone_call_init_common(call, from, to);
call->log->call_id=ms_strdup(sal_op_get_call_id(op)); /*must be known at that time*/
linphone_core_init_default_params(lc, &call->params);
@ -510,6 +561,21 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro
case LinphonePolicyUseStun:
call->ping_time=linphone_core_run_stun_tests(call->core,call);
/* No break to also destroy ice session in this case. */
break;
case LinphonePolicyUseUpnp:
#ifdef BUILD_UPNP
if(!lc->rtp_conf.disable_upnp) {
call->upnp_session = linphone_upnp_session_new(call);
if (call->upnp_session != NULL) {
linphone_call_init_media_streams(call);
if (linphone_core_update_upnp_from_remote_media_description(call, sal_call_get_remote_media_description(op))<0) {
/* uPnP port mappings failed, proceed with the call anyway. */
linphone_call_delete_upnp_session(call);
}
}
}
#endif //BUILD_UPNP
break;
default:
break;
}
@ -658,6 +724,9 @@ void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const
static void linphone_call_destroy(LinphoneCall *obj)
{
#ifdef BUILD_UPNP
linphone_call_delete_upnp_session(obj);
#endif //BUILD_UPNP
linphone_call_delete_ice_session(obj);
if (obj->op!=NULL) {
sal_op_release(obj->op);
@ -682,7 +751,7 @@ static void linphone_call_destroy(LinphoneCall *obj)
if (obj->auth_token) {
ms_free(obj->auth_token);
}
linphone_call_params_uninit(&obj->params);
ms_free(obj);
}
@ -717,7 +786,9 @@ void linphone_call_unref(LinphoneCall *obj){
/**
* Returns current parameters associated to the call.
**/
const LinphoneCallParams * linphone_call_get_current_params(const LinphoneCall *call){
const LinphoneCallParams * linphone_call_get_current_params(LinphoneCall *call){
if (call->params.record_file)
call->current_params.record_file=call->params.record_file;
return &call->current_params;
}
@ -755,6 +826,7 @@ const LinphoneCallParams * linphone_call_get_remote_params(LinphoneCall *call){
cp->low_bandwidth=TRUE;
}
}
cp->custom_headers=(SalCustomHeader*)sal_op_get_custom_header(call->op);
return cp;
}
}
@ -847,6 +919,16 @@ const char *linphone_call_get_remote_user_agent(LinphoneCall *call){
return NULL;
}
/**
* Returns the far end's sip contact as a string, if available.
**/
const char *linphone_call_get_remote_contact(LinphoneCall *call){
if (call->op){
return sal_op_get_remote_contact(call->op);
}
return NULL;
}
/**
* Returns true if this calls has received a transfer that has not been
* executed yet.
@ -898,6 +980,18 @@ void linphone_call_enable_camera (LinphoneCall *call, bool_t enable){
#endif
}
#ifdef VIDEO_ENABLED
/**
* Request remote side to send us a Video Fast Update.
**/
void linphone_call_send_vfu_request(LinphoneCall *call)
{
if (LinphoneCallStreamsRunning == linphone_call_get_state(call))
sal_call_send_vfu_request(call->op);
}
#endif
/**
* Take a photo of currently received video and write it into a jpeg file.
**/
@ -926,10 +1020,17 @@ void linphone_call_params_enable_video(LinphoneCallParams *cp, bool_t enabled){
cp->has_video=enabled;
}
/**
* Returns the audio codec used in the call, described as a PayloadType structure.
**/
const PayloadType* linphone_call_params_get_used_audio_codec(const LinphoneCallParams *cp) {
return cp->audio_codec;
}
/**
* Returns the video codec used in the call, described as a PayloadType structure.
**/
const PayloadType* linphone_call_params_get_used_video_codec(const LinphoneCallParams *cp) {
return cp->video_codec;
}
@ -966,10 +1067,16 @@ bool_t linphone_call_params_video_enabled(const LinphoneCallParams *cp){
return cp->has_video;
}
/**
* Returns kind of media encryption selected for the call.
**/
enum LinphoneMediaEncryption linphone_call_params_get_media_encryption(const LinphoneCallParams *cp) {
return cp->media_encryption;
}
/**
* Set requested media encryption for a call.
**/
void linphone_call_params_set_media_encryption(LinphoneCallParams *cp, enum LinphoneMediaEncryption e) {
cp->media_encryption = e;
}
@ -982,6 +1089,9 @@ void linphone_call_params_enable_early_media_sending(LinphoneCallParams *cp, boo
cp->real_early_media=enabled;
}
/**
* Indicates whether sending of early media was enabled.
**/
bool_t linphone_call_params_early_media_sending_enabled(const LinphoneCallParams *cp){
return cp->real_early_media;
}
@ -1001,33 +1111,46 @@ void linphone_call_params_set_audio_bandwidth_limit(LinphoneCallParams *cp, int
cp->audio_bw=bandwidth;
}
#ifdef VIDEO_ENABLED
/**
* Request remote side to send us a Video Fast Update.
**/
void linphone_call_send_vfu_request(LinphoneCall *call)
{
if (LinphoneCallStreamsRunning == linphone_call_get_state(call))
sal_call_send_vfu_request(call->op);
void linphone_call_params_add_custom_header(LinphoneCallParams *params, const char *header_name, const char *header_value){
params->custom_headers=sal_custom_header_append(params->custom_headers,header_name,header_value);
}
const char *linphone_call_params_get_custom_header(const LinphoneCallParams *params, const char *header_name){
return sal_custom_header_find(params->custom_headers,header_name);
}
void _linphone_call_params_copy(LinphoneCallParams *ncp, const LinphoneCallParams *cp){
memcpy(ncp,cp,sizeof(LinphoneCallParams));
if (cp->record_file) ncp->record_file=ms_strdup(cp->record_file);
/*
* The management of the custom headers is not optimal. We copy everything while ref counting would be more efficient.
*/
if (cp->custom_headers) ncp->custom_headers=sal_custom_header_clone(cp->custom_headers);
}
#endif
/**
*
* Copy existing LinphoneCallParams to a new LinphoneCallParams object.
**/
LinphoneCallParams * linphone_call_params_copy(const LinphoneCallParams *cp){
LinphoneCallParams *ncp=ms_new0(LinphoneCallParams,1);
memcpy(ncp,cp,sizeof(LinphoneCallParams));
_linphone_call_params_copy(ncp,cp);
return ncp;
}
void linphone_call_params_uninit(LinphoneCallParams *p){
if (p->record_file) ms_free(p->record_file);
if (p->custom_headers) sal_custom_header_free(p->custom_headers);
}
/**
*
* Destroy LinphoneCallParams.
**/
void linphone_call_params_destroy(LinphoneCallParams *p){
linphone_call_params_uninit(p);
ms_free(p);
}
/**
* @}
**/
@ -1268,10 +1391,10 @@ static void post_configure_audio_streams(LinphoneCall*call){
LinphoneCore *lc=call->core;
_post_configure_audio_stream(st,lc,call->audio_muted);
if (lc->vtable.dtmf_received!=NULL){
/* replace by our default action*/
audio_stream_play_received_dtmfs(call->audiostream,FALSE);
/*rtp_session_signal_connect(call->audiostream->session,"telephone-event",(RtpCallback)linphone_core_dtmf_received,(unsigned long)lc);*/
}
if (call->record_active)
linphone_call_start_recording(call);
}
static RtpProfile *make_profile(LinphoneCall *call, const SalMediaDescription *md, const SalStreamDescription *desc, int *used_pt){
@ -1423,6 +1546,8 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna
if (captcard && stream->max_rate>0) ms_snd_card_set_preferred_sample_rate(captcard, stream->max_rate);
audio_stream_enable_adaptive_bitrate_control(call->audiostream,use_arc);
audio_stream_enable_adaptive_jittcomp(call->audiostream, linphone_core_audio_adaptive_jittcomp_enabled(lc));
if (!call->params.in_conference && call->params.record_file)
audio_stream_mixed_record_open(call->audiostream,call->params.record_file);
audio_stream_start_full(
call->audiostream,
call->audio_profile,
@ -1451,23 +1576,23 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna
}
audio_stream_set_rtcp_information(call->audiostream, cname, rtcp_tool);
/* valid local tags are > 0 */
/* valid local tags are > 0 */
if (stream->proto == SalProtoRtpSavp) {
const SalStreamDescription *local_st_desc=sal_media_description_find_stream(call->localdesc,
SalProtoRtpSavp,SalAudio);
int crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, stream->crypto_local_tag);
if (crypto_idx >= 0) {
audio_stream_enable_srtp(
call->audiostream,
stream->crypto[0].algo,
local_st_desc->crypto[crypto_idx].master_key,
stream->crypto[0].master_key);
call->audiostream_encrypted=TRUE;
} else {
ms_warning("Failed to find local crypto algo with tag: %d", stream->crypto_local_tag);
call->audiostream_encrypted=FALSE;
}
const SalStreamDescription *local_st_desc=sal_media_description_find_stream(call->localdesc,
SalProtoRtpSavp,SalAudio);
int crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, stream->crypto_local_tag);
if (crypto_idx >= 0) {
audio_stream_enable_srtp(
call->audiostream,
stream->crypto[0].algo,
local_st_desc->crypto[crypto_idx].master_key,
stream->crypto[0].master_key);
call->audiostream_encrypted=TRUE;
} else {
ms_warning("Failed to find local crypto algo with tag: %d", stream->crypto_local_tag);
call->audiostream_encrypted=FALSE;
}
}else call->audiostream_encrypted=FALSE;
if (call->params.in_conference){
/*transform the graph to connect it to the conference filter */
@ -1506,11 +1631,11 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna
const char *rtcp_addr=vstream->rtcp_addr[0]!='\0' ? vstream->rtcp_addr : call->resultdesc->addr;
call->video_profile=make_profile(call,call->resultdesc,vstream,&used_pt);
if (used_pt!=-1){
call->current_params.video_codec = rtp_profile_get_payload(call->video_profile, used_pt);
VideoStreamDir dir=VideoStreamSendRecv;
MSWebCam *cam=lc->video_conf.device;
bool_t is_inactive=FALSE;
call->current_params.video_codec = rtp_profile_get_payload(call->video_profile, used_pt);
call->current_params.has_video=TRUE;
video_stream_enable_adaptive_bitrate_control(call->videostream,
@ -1580,9 +1705,6 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna
void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_muted, bool_t send_ringbacktone){
LinphoneCore *lc=call->core;
call->current_params.audio_codec = NULL;
call->current_params.video_codec = NULL;
LinphoneAddress *me=linphone_core_get_primary_contact_parsed(lc);
char *cname;
bool_t use_arc=linphone_core_adaptive_rate_control_enabled(lc);
@ -1591,6 +1713,9 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut
SalProtoRtpAvp,SalVideo);
#endif
call->current_params.audio_codec = NULL;
call->current_params.video_codec = NULL;
if ((call->audiostream == NULL) && (call->videostream == NULL)) {
ms_fatal("start_media_stream() called without prior init !");
return;
@ -1667,18 +1792,20 @@ void linphone_call_update_crypto_parameters(LinphoneCall *call, SalMediaDescript
new_stream = sal_media_description_find_stream(new_md, SalProtoRtpSavp, SalAudio);
if (old_stream && new_stream) {
const SalStreamDescription *local_st_desc = sal_media_description_find_stream(call->localdesc, SalProtoRtpSavp, SalAudio);
int crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, new_stream->crypto_local_tag);
if (crypto_idx >= 0) {
audio_stream_enable_srtp(call->audiostream, new_stream->crypto[0].algo, local_st_desc->crypto[crypto_idx].master_key, new_stream->crypto[0].master_key);
call->audiostream_encrypted = TRUE;
} else {
ms_warning("Failed to find local crypto algo with tag: %d", new_stream->crypto_local_tag);
call->audiostream_encrypted = FALSE;
}
for (i = 0; i < SAL_CRYPTO_ALGO_MAX; i++) {
old_stream->crypto[i].tag = new_stream->crypto[i].tag;
old_stream->crypto[i].algo = new_stream->crypto[i].algo;
strncpy(old_stream->crypto[i].master_key, new_stream->crypto[i].master_key, sizeof(old_stream->crypto[i].master_key) - 1);
if (local_st_desc) {
int crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, new_stream->crypto_local_tag);
if (crypto_idx >= 0) {
audio_stream_enable_srtp(call->audiostream, new_stream->crypto[0].algo, local_st_desc->crypto[crypto_idx].master_key, new_stream->crypto[0].master_key);
call->audiostream_encrypted = TRUE;
} else {
ms_warning("Failed to find local crypto algo with tag: %d", new_stream->crypto_local_tag);
call->audiostream_encrypted = FALSE;
}
for (i = 0; i < SAL_CRYPTO_ALGO_MAX; i++) {
old_stream->crypto[i].tag = new_stream->crypto[i].tag;
old_stream->crypto[i].algo = new_stream->crypto[i].algo;
strncpy(old_stream->crypto[i].master_key, new_stream->crypto[i].master_key, sizeof(old_stream->crypto[i].master_key) - 1);
}
}
}
@ -1687,23 +1814,33 @@ void linphone_call_update_crypto_parameters(LinphoneCall *call, SalMediaDescript
new_stream = sal_media_description_find_stream(new_md, SalProtoRtpSavp, SalVideo);
if (old_stream && new_stream) {
const SalStreamDescription *local_st_desc = sal_media_description_find_stream(call->localdesc, SalProtoRtpSavp, SalVideo);
int crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, new_stream->crypto_local_tag);
if (crypto_idx >= 0) {
video_stream_enable_strp(call->videostream, new_stream->crypto[0].algo, local_st_desc->crypto[crypto_idx].master_key, new_stream->crypto[0].master_key);
call->videostream_encrypted = TRUE;
} else {
ms_warning("Failed to find local crypto algo with tag: %d", new_stream->crypto_local_tag);
call->videostream_encrypted = FALSE;
}
for (i = 0; i < SAL_CRYPTO_ALGO_MAX; i++) {
old_stream->crypto[i].tag = new_stream->crypto[i].tag;
old_stream->crypto[i].algo = new_stream->crypto[i].algo;
strncpy(old_stream->crypto[i].master_key, new_stream->crypto[i].master_key, sizeof(old_stream->crypto[i].master_key) - 1);
if (local_st_desc) {
int crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, new_stream->crypto_local_tag);
if (crypto_idx >= 0) {
video_stream_enable_strp(call->videostream, new_stream->crypto[0].algo, local_st_desc->crypto[crypto_idx].master_key, new_stream->crypto[0].master_key);
call->videostream_encrypted = TRUE;
} else {
ms_warning("Failed to find local crypto algo with tag: %d", new_stream->crypto_local_tag);
call->videostream_encrypted = FALSE;
}
for (i = 0; i < SAL_CRYPTO_ALGO_MAX; i++) {
old_stream->crypto[i].tag = new_stream->crypto[i].tag;
old_stream->crypto[i].algo = new_stream->crypto[i].algo;
strncpy(old_stream->crypto[i].master_key, new_stream->crypto[i].master_key, sizeof(old_stream->crypto[i].master_key) - 1);
}
}
}
#endif
}
void linphone_call_update_remote_session_id_and_ver(LinphoneCall *call) {
SalMediaDescription *remote_desc = sal_call_get_remote_media_description(call->op);
if (remote_desc) {
call->remote_session_id = remote_desc->session_id;
call->remote_session_ver = remote_desc->session_ver;
}
}
void linphone_call_delete_ice_session(LinphoneCall *call){
if (call->ice_session != NULL) {
ice_session_destroy(call->ice_session);
@ -1715,9 +1852,22 @@ void linphone_call_delete_ice_session(LinphoneCall *call){
}
}
static void linphone_call_log_fill_stats(LinphoneCallLog *log, AudioStream *st){
audio_stream_get_local_rtp_stats (st,&log->local_stats);
log->quality=audio_stream_get_average_quality_rating(st);
#ifdef BUILD_UPNP
void linphone_call_delete_upnp_session(LinphoneCall *call){
if(call->upnp_session!=NULL) {
linphone_upnp_session_destroy(call->upnp_session);
call->upnp_session=NULL;
}
}
#endif //BUILD_UPNP
static void linphone_call_log_fill_stats(LinphoneCallLog *log, MediaStream *st){
float quality=media_stream_get_average_quality_rating(st);
if (quality>=0){
if (log->quality!=-1){
log->quality*=quality/5.0;
}else log->quality=quality;
}
}
void linphone_call_stop_audio_stream(LinphoneCall *call) {
@ -1735,7 +1885,8 @@ void linphone_call_stop_audio_stream(LinphoneCall *call) {
lp_config_set_string(call->core->config,"sound","ec_state",state_str);
}
}
linphone_call_log_fill_stats (call->log,call->audiostream);
audio_stream_get_local_rtp_stats(call->audiostream,&call->log->local_stats);
linphone_call_log_fill_stats (call->log,(MediaStream*)call->audiostream);
if (call->endpoint){
linphone_call_remove_from_conf(call);
}
@ -1751,6 +1902,7 @@ void linphone_call_stop_video_stream(LinphoneCall *call) {
ortp_ev_queue_flush(call->videostream_app_evq);
ortp_ev_queue_destroy(call->videostream_app_evq);
call->videostream_app_evq=NULL;
linphone_call_log_fill_stats(call->log,(MediaStream*)call->videostream);
video_stream_stop(call->videostream);
call->videostream=NULL;
}
@ -1867,10 +2019,20 @@ float linphone_call_get_record_volume(LinphoneCall *call){
* active audio stream exist. Otherwise it returns the quality rating.
**/
float linphone_call_get_current_quality(LinphoneCall *call){
float audio_rating=-1;
float video_rating=-1;
float result;
if (call->audiostream){
return audio_stream_get_quality_rating(call->audiostream);
audio_rating=media_stream_get_quality_rating((MediaStream*)call->audiostream)/5.0;
}
return -1;
if (call->videostream){
video_rating=media_stream_get_quality_rating((MediaStream*)call->videostream)/5.0;
}
if (audio_rating<0 && video_rating<0) result=-1;
else if (audio_rating<0) result=video_rating*5.0;
else if (video_rating<0) result=audio_rating*5.0;
else result=audio_rating*video_rating*5.0;
return result;
}
/**
@ -1885,20 +2047,83 @@ float linphone_call_get_average_quality(LinphoneCall *call){
return -1;
}
static void update_local_stats(LinphoneCallStats *stats, MediaStream *stream){
const MSQualityIndicator *qi=media_stream_get_quality_indicator(stream);
if (qi) {
stats->local_late_rate=ms_quality_indicator_get_local_late_rate(qi);
stats->local_loss_rate=ms_quality_indicator_get_local_loss_rate(qi);
}
}
/**
* Access last known statistics for audio stream, for a given call.
**/
const LinphoneCallStats *linphone_call_get_audio_stats(const LinphoneCall *call) {
return &call->stats[LINPHONE_CALL_STATS_AUDIO];
const LinphoneCallStats *linphone_call_get_audio_stats(LinphoneCall *call) {
LinphoneCallStats *stats=&call->stats[LINPHONE_CALL_STATS_AUDIO];
if (call->audiostream){
update_local_stats(stats,(MediaStream*)call->audiostream);
}
return stats;
}
/**
* Access last known statistics for video stream, for a given call.
**/
const LinphoneCallStats *linphone_call_get_video_stats(const LinphoneCall *call) {
return &call->stats[LINPHONE_CALL_STATS_VIDEO];
const LinphoneCallStats *linphone_call_get_video_stats(LinphoneCall *call) {
LinphoneCallStats *stats=&call->stats[LINPHONE_CALL_STATS_VIDEO];
if (call->videostream){
update_local_stats(stats,(MediaStream*)call->videostream);
}
return stats;
}
/**
* Enable recording of the call (voice-only).
* This function must be used before the call parameters are assigned to the call.
* The call recording can be started and paused after the call is established with
* linphone_call_start_recording() and linphone_call_pause_recording().
* @param cp the call parameters
* @param path path and filename of the file where audio is written.
**/
void linphone_call_params_set_record_file(LinphoneCallParams *cp, const char *path){
if (cp->record_file){
ms_free(cp->record_file);
cp->record_file=NULL;
}
if (path) cp->record_file=ms_strdup(path);
}
/**
* Retrieves the path for the audio recoding of the call.
**/
const char *linphone_call_params_get_record_file(const LinphoneCallParams *cp){
return cp->record_file;
}
/**
* Start call recording.
* The output file where audio is recorded must be previously specified with linphone_call_params_set_record_file().
**/
void linphone_call_start_recording(LinphoneCall *call){
if (!call->params.record_file){
ms_error("linphone_call_start_recording(): no output file specified. Use linphone_call_params_set_record_file().");
return;
}
if (call->audiostream && !call->params.in_conference){
audio_stream_mixed_record_start(call->audiostream);
}
call->record_active=TRUE;
}
/**
* Stop call recording.
**/
void linphone_call_stop_recording(LinphoneCall *call){
if (call->audiostream && !call->params.in_conference){
audio_stream_mixed_record_stop(call->audiostream);
}
call->record_active=FALSE;
}
/**
* @}
@ -1925,7 +2150,7 @@ static void linphone_core_disconnected(LinphoneCore *lc, LinphoneCall *call){
if (from)
{
snprintf(temp,sizeof(temp),"Remote end %s seems to have disconnected, the call is going to be closed.",from);
free(from);
ms_free(from);
}
else
{
@ -1934,6 +2159,7 @@ static void linphone_core_disconnected(LinphoneCore *lc, LinphoneCall *call){
if (lc->vtable.display_warning!=NULL)
lc->vtable.display_warning(lc,temp);
linphone_core_terminate_call(lc,call);
linphone_core_play_named_tone(lc,LinphoneToneCallFailed);
}
static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){
@ -2025,6 +2251,11 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse
report_bandwidth(call,as,vs);
ms_message("Thread processing load: audio=%f\tvideo=%f",audio_load,video_load);
}
#ifdef BUILD_UPNP
linphone_upnp_call_process(call);
#endif //BUILD_UPNP
#ifdef VIDEO_ENABLED
if (call->videostream!=NULL) {
OrtpEvent *ev;
@ -2047,6 +2278,7 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse
freemsg(call->stats[LINPHONE_CALL_STATS_VIDEO].received_rtcp);
call->stats[LINPHONE_CALL_STATS_VIDEO].received_rtcp = evd->packet;
evd->packet = NULL;
update_local_stats(&call->stats[LINPHONE_CALL_STATS_VIDEO],(MediaStream*)call->videostream);
if (lc->vtable.call_stats_updated)
lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_VIDEO]);
} else if (evt == ORTP_EVENT_RTCP_PACKET_EMITTED) {
@ -2055,6 +2287,7 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse
freemsg(call->stats[LINPHONE_CALL_STATS_VIDEO].sent_rtcp);
call->stats[LINPHONE_CALL_STATS_VIDEO].sent_rtcp = evd->packet;
evd->packet = NULL;
update_local_stats(&call->stats[LINPHONE_CALL_STATS_VIDEO],(MediaStream*)call->videostream);
if (lc->vtable.call_stats_updated)
lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_VIDEO]);
} else if ((evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) || (evt == ORTP_EVENT_ICE_GATHERING_FINISHED)
@ -2088,6 +2321,7 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse
freemsg(call->stats[LINPHONE_CALL_STATS_AUDIO].received_rtcp);
call->stats[LINPHONE_CALL_STATS_AUDIO].received_rtcp = evd->packet;
evd->packet = NULL;
update_local_stats(&call->stats[LINPHONE_CALL_STATS_AUDIO],(MediaStream*)call->audiostream);
if (lc->vtable.call_stats_updated)
lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_AUDIO]);
} else if (evt == ORTP_EVENT_RTCP_PACKET_EMITTED) {
@ -2096,6 +2330,7 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse
freemsg(call->stats[LINPHONE_CALL_STATS_AUDIO].sent_rtcp);
call->stats[LINPHONE_CALL_STATS_AUDIO].sent_rtcp = evd->packet;
evd->packet = NULL;
update_local_stats(&call->stats[LINPHONE_CALL_STATS_AUDIO],(MediaStream*)call->audiostream);
if (lc->vtable.call_stats_updated)
lc->vtable.call_stats_updated(lc, call, &call->stats[LINPHONE_CALL_STATS_AUDIO]);
} else if ((evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) || (evt == ORTP_EVENT_ICE_GATHERING_FINISHED)

File diff suppressed because it is too large Load diff

View file

@ -37,26 +37,40 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
extern "C" {
#endif
struct _MSSndCard;
struct _LinphoneCore;
/**
* Linphone core main object created by function linphone_core_new() .
* @ingroup initializing
*/
typedef struct _LinphoneCore LinphoneCore;
struct SalOp;
struct _LpConfig;
struct _LCSipTransports{
/**
* Linphone core SIP transport ports.
* Use with #linphone_core_set_sip_transports
* @ingroup initializing
*/
typedef struct _LCSipTransports{
/**
* udp port to listening on, negative value if not set
* */
int udp_port;
/**
* tcp port to listening on, negative value if not set
* */
int tcp_port;
/**
* dtls port to listening on, negative value if not set
* */
int dtls_port;
/**
* tls port to listening on, negative value if not set
* */
int tls_port;
};
} LCSipTransports;
typedef struct _LCSipTransports LCSipTransports;
/**
* Object that represents a SIP address.
@ -141,24 +155,7 @@ typedef enum _LinphoneCallStatus {
* @ingroup call_logs
*
**/
typedef struct _LinphoneCallLog{
LinphoneCallDir dir; /**< The direction of the call*/
LinphoneCallStatus status; /**< The status of the call*/
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*/
char *refkey;
void *user_pointer;
rtp_stats_t local_stats;
rtp_stats_t remote_stats;
float quality;
int video_enabled;
struct _LinphoneCore *lc;
time_t start_date_time; /**Start date of the call in seconds as expressed in a time_t */
const char* call_id; /**unique id of a call*/
} LinphoneCallLog;
typedef struct _LinphoneCallLog LinphoneCallLog;
/**
* Enum describing type of media encryption types.
@ -175,12 +172,22 @@ enum LinphoneMediaEncryption {
typedef enum LinphoneMediaEncryption LinphoneMediaEncryption;
/*public: */
LinphoneAddress *linphone_call_log_get_from(LinphoneCallLog *cl);
LinphoneAddress *linphone_call_log_get_to(LinphoneCallLog *cl);
LinphoneAddress *linphone_call_log_get_remote_address(LinphoneCallLog *cl);
LinphoneCallDir linphone_call_log_get_dir(LinphoneCallLog *cl);
LinphoneCallStatus linphone_call_log_get_status(LinphoneCallLog *cl);
LinphoneCallStatus linphone_call_log_video_enabled(LinphoneCallLog *cl);
time_t linphone_call_log_get_start_date(LinphoneCallLog *cl);
int linphone_call_log_get_duration(LinphoneCallLog *cl);
float linphone_call_log_get_quality(LinphoneCallLog *cl);
void linphone_call_log_set_user_pointer(LinphoneCallLog *cl, void *up);
void *linphone_call_log_get_user_pointer(const LinphoneCallLog *cl);
void linphone_call_log_set_ref_key(LinphoneCallLog *cl, const char *refkey);
const char *linphone_call_log_get_ref_key(const LinphoneCallLog *cl);
const rtp_stats_t *linphone_call_log_get_local_stats(const LinphoneCallLog *cl);
const rtp_stats_t *linphone_call_log_get_remote_stats(const LinphoneCallLog *cl);
const char *linphone_call_log_get_call_id(const LinphoneCallLog *cl);
char * linphone_call_log_to_str(LinphoneCallLog *cl);
struct _LinphoneCallParams;
@ -206,7 +213,10 @@ void linphone_call_params_set_audio_bandwidth_limit(LinphoneCallParams *cp, int
void linphone_call_params_destroy(LinphoneCallParams *cp);
bool_t linphone_call_params_low_bandwidth_enabled(const LinphoneCallParams *cp);
void linphone_call_params_enable_low_bandwidth(LinphoneCallParams *cp, bool_t enabled);
void linphone_call_params_set_record_file(LinphoneCallParams *cp, const char *path);
const char *linphone_call_params_get_record_file(const LinphoneCallParams *cp);
void linphone_call_params_add_custom_header(LinphoneCallParams *params, const char *header_name, const char *header_value);
const char *linphone_call_params_get_custom_header(const LinphoneCallParams *params, const char *header_name);
/**
* Enum describing failure reasons.
* @ingroup initializing
@ -284,6 +294,27 @@ enum _LinphoneIceState{
**/
typedef enum _LinphoneIceState LinphoneIceState;
/**
* Enum describing uPnP states.
* @ingroup initializing
**/
enum _LinphoneUpnpState{
LinphoneUpnpStateIdle, /**< uPnP is not activate */
LinphoneUpnpStatePending, /**< uPnP process is in progress */
LinphoneUpnpStateAdding, /**< Internal use: Only used by port binding */
LinphoneUpnpStateRemoving, /**< Internal use: Only used by port binding */
LinphoneUpnpStateNotAvailable, /**< uPnP is not available */
LinphoneUpnpStateOk, /**< uPnP is enabled */
LinphoneUpnpStateKo, /**< uPnP processing has failed */
};
/**
* Enum describing uPnP states.
* @ingroup initializing
**/
typedef enum _LinphoneUpnpState LinphoneUpnpState;
/**
* The LinphoneCallStats objects carries various statistic informations regarding quality of audio or video streams.
*
@ -309,16 +340,19 @@ struct _LinphoneCallStats {
mblk_t* sent_rtcp;/**<Last RTCP packet sent, as a mblk_t structure. See oRTP documentation for details how to extract information from it*/
float round_trip_delay; /**<Round trip propagation time in seconds if known, -1 if unknown.*/
LinphoneIceState ice_state; /**< State of ICE processing. */
LinphoneUpnpState upnp_state; /**< State of uPnP processing. */
float download_bandwidth; /**<Download bandwidth measurement of received stream, expressed in kbit/s, including IP/UDP/RTP headers*/
float upload_bandwidth; /**<Download bandwidth measurement of sent stream, expressed in kbit/s, including IP/UDP/RTP headers*/
float local_late_rate; /**<percentage of packet received too late over last second*/
float local_loss_rate; /**<percentage of lost packet over last second*/
};
/**
* @}
**/
const LinphoneCallStats *linphone_call_get_audio_stats(const LinphoneCall *call);
const LinphoneCallStats *linphone_call_get_video_stats(const LinphoneCall *call);
const LinphoneCallStats *linphone_call_get_audio_stats(LinphoneCall *call);
const LinphoneCallStats *linphone_call_get_video_stats(LinphoneCall *call);
/** Callback prototype */
@ -367,13 +401,14 @@ const char *linphone_call_get_refer_to(const LinphoneCall *call);
bool_t linphone_call_has_transfer_pending(const LinphoneCall *call);
LinphoneCall *linphone_call_get_replaced_call(LinphoneCall *call);
int linphone_call_get_duration(const LinphoneCall *call);
const LinphoneCallParams * linphone_call_get_current_params(const LinphoneCall *call);
const LinphoneCallParams * linphone_call_get_current_params(LinphoneCall *call);
const LinphoneCallParams * linphone_call_get_remote_params(LinphoneCall *call);
void linphone_call_enable_camera(LinphoneCall *lc, bool_t enabled);
bool_t linphone_call_camera_enabled(const LinphoneCall *lc);
int linphone_call_take_video_snapshot(LinphoneCall *call, const char *file);
LinphoneReason linphone_call_get_reason(const LinphoneCall *call);
const char *linphone_call_get_remote_user_agent(LinphoneCall *call);
const char *linphone_call_get_remote_contact(LinphoneCall *call);
float linphone_call_get_play_volume(LinphoneCall *call);
float linphone_call_get_record_volume(LinphoneCall *call);
float linphone_call_get_current_quality(LinphoneCall *call);
@ -387,6 +422,8 @@ void linphone_call_set_user_pointer(LinphoneCall *call, void *user_pointer);
void linphone_call_set_next_video_frame_decoded_callback(LinphoneCall *call, LinphoneCallCbFunc cb, void* user_data);
LinphoneCallState linphone_call_get_transfer_state(LinphoneCall *call);
void linphone_call_zoom_video(LinphoneCall* call, float zoom_factor, float* cx, float* cy);
void linphone_call_start_recording(LinphoneCall *call);
void linphone_call_stop_recording(LinphoneCall *call);
/**
* Return TRUE if this call is currently part of a conference
*@param call #LinphoneCall
@ -598,10 +635,14 @@ LinphoneAuthInfo *linphone_auth_info_new(const char *username, const char *useri
void linphone_auth_info_set_passwd(LinphoneAuthInfo *info, const char *passwd);
void linphone_auth_info_set_username(LinphoneAuthInfo *info, const char *username);
void linphone_auth_info_set_userid(LinphoneAuthInfo *info, const char *userid);
void linphone_auth_info_set_realm(LinphoneAuthInfo *info, const char *realm);
void linphone_auth_info_set_ha1(LinphoneAuthInfo *info, const char *ha1);
const char *linphone_auth_info_get_username(const LinphoneAuthInfo *i);
const char *linphone_auth_info_get_passwd(const LinphoneAuthInfo *i);
const char *linphone_auth_info_get_userid(const LinphoneAuthInfo *i);
const char *linphone_auth_info_get_realm(const LinphoneAuthInfo *i);
const char *linphone_auth_info_get_ha1(const LinphoneAuthInfo *i);
/* you don't need those function*/
void linphone_auth_info_destroy(LinphoneAuthInfo *info);
@ -626,37 +667,6 @@ typedef struct _LinphoneChatMessage LinphoneChatMessage;
*/
typedef struct _LinphoneChatRoom LinphoneChatRoom;
/**
* Create a new chat room for messaging from a sip uri like sip:joe@sip.linphone.org
* @param lc #LinphoneCore object
* @param to destination address for messages
* @return #LinphoneChatRoom where messaging can take place.
*/
LinphoneChatRoom * linphone_core_create_chat_room(LinphoneCore *lc, const char *to);
/**
* Destructor
* @param cr #LinphoneChatRoom object
*/
void linphone_chat_room_destroy(LinphoneChatRoom *cr);
/**
* create a message attached to a dedicated chat room;
*/
LinphoneChatMessage* linphone_chat_room_create_message(const LinphoneChatRoom *cr,const char* message);
/**
* get peer address \link linphone_core_create_chat_room() associated to \endlink this #LinphoneChatRoom
* @param cr #LinphoneChatRoom object
* @return #LinphoneAddress peer address
*/
const LinphoneAddress* linphone_chat_room_get_peer_address(LinphoneChatRoom *cr);
/**
* send a message to peer member of this chat room.
* @param cr #LinphoneChatRoom object
* @param msg message to be sent
*/
void linphone_chat_room_send_message(LinphoneChatRoom *cr, const char *msg);
/**
*LinphoneChatMessageState is used to notify if messages have been succesfully delivered or not.
*/
@ -667,62 +677,6 @@ typedef enum _LinphoneChatMessageStates {
LinphoneChatMessageStateNotDelivered /**<message was not delivered*/
}LinphoneChatMessageState;
/**
* to string function
*/
const char* linphone_chat_message_state_to_string(const LinphoneChatMessageState state);
/**
* Clone a chat message
*@param message #LinphoneChatMessage obj
*@return #LinphoneChatMessage
*/
LinphoneChatMessage* linphone_chat_message_clone(const LinphoneChatMessage* message);
/**
* Set origin of the message
*@param message #LinphoneChatMessage obj
*@param from #LinphoneAddress origin of this message (copied)
*/
void linphone_chat_message_set_from(LinphoneChatMessage* message, const LinphoneAddress* from);
/**
* Get origin of the message
*@param message #LinphoneChatMessage obj
*@return #LinphoneAddress
*/
LinphoneAddress* linphone_chat_message_get_from(const LinphoneChatMessage* message);
/**
* Linphone message can carry external body as defined by rfc2017
* @param message #LinphoneChatMessage
* @return external body url or NULL if not present.
*/
const char* linphone_chat_message_get_external_body_url(const LinphoneChatMessage* message);
/**
* Linphone message can carry external body as defined by rfc2017
*
* @param message a LinphoneChatMessage
* @param url ex: access-type=URL; URL="http://www.foo.com/file"
*/
void linphone_chat_message_set_external_body_url(LinphoneChatMessage* message,const char* url);
/**
* Get text part of this message
* @return text or NULL if no text.
*/
const char * linphone_chat_message_get_text(const LinphoneChatMessage* message);
/**
* user pointer get function
*/
void* linphone_chat_message_get_user_data(const LinphoneChatMessage* message);
/**
* user pointer set function
*/
void linphone_chat_message_set_user_data(LinphoneChatMessage* message,void*);
/**
* Call back used to notify message delivery status
*@param msg #LinphoneChatMessage object
@ -730,21 +684,42 @@ void linphone_chat_message_set_user_data(LinphoneChatMessage* message,void*);
*@param ud application user data
*/
typedef void (*LinphoneChatMessageStateChangeCb)(LinphoneChatMessage* msg,LinphoneChatMessageState state,void* ud);
/**
* send a message to peer member of this chat room.
* @param cr #LinphoneChatRoom object
* @param msg #LinphoneChatMessage message to be sent
* @param status_cb LinphoneChatMessageStateChangeCb status callback invoked when message is delivered or could not be delivered. May be NULL
* @param ud user data for the status cb.
*/
void linphone_core_set_chat_database_path(LinphoneCore *lc, const char *path);
LinphoneChatRoom * linphone_core_create_chat_room(LinphoneCore *lc, const char *to);
LinphoneChatRoom *linphone_core_get_chat_room(LinphoneCore *lc, const LinphoneAddress *addr);
void linphone_chat_room_destroy(LinphoneChatRoom *cr);
LinphoneChatMessage* linphone_chat_room_create_message(LinphoneChatRoom *cr,const char* message);
const LinphoneAddress* linphone_chat_room_get_peer_address(LinphoneChatRoom *cr);
void linphone_chat_room_send_message(LinphoneChatRoom *cr, const char *msg);
void linphone_chat_room_send_message2(LinphoneChatRoom *cr, LinphoneChatMessage* msg,LinphoneChatMessageStateChangeCb status_cb,void* ud);
MSList *linphone_chat_room_get_history(LinphoneChatRoom *cr,int nb_message);
void linphone_chat_room_mark_as_read(LinphoneChatRoom *cr);
void linphone_chat_room_delete_history(LinphoneChatRoom *cr);
int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr);
LinphoneCore* linphone_chat_room_get_lc(LinphoneChatRoom *cr);
LinphoneChatRoom* linphone_chat_message_get_chat_room(LinphoneChatMessage *msg);
char* linphone_chat_message_get_message(LinphoneChatMessage *msg);
const LinphoneAddress* linphone_chat_message_get_peer_address(LinphoneChatMessage *msg);
void linphone_chat_room_set_user_data(LinphoneChatRoom *cr, void * ud);
void * linphone_chat_room_get_user_data(LinphoneChatRoom *cr);
LinphoneChatMessageState linphone_chat_message_get_state(const LinphoneChatMessage* message);
const char* linphone_chat_message_state_to_string(const LinphoneChatMessageState state);
LinphoneChatMessage* linphone_chat_message_clone(const LinphoneChatMessage* message);
void linphone_chat_message_destroy(LinphoneChatMessage* msg);
void linphone_chat_message_set_from(LinphoneChatMessage* message, const LinphoneAddress* from);
const LinphoneAddress* linphone_chat_message_get_from(const LinphoneChatMessage* message);
const LinphoneAddress* linphone_chat_message_get_to(const LinphoneChatMessage* message);
const char* linphone_chat_message_get_external_body_url(const LinphoneChatMessage* message);
void linphone_chat_message_set_external_body_url(LinphoneChatMessage* message,const char* url);
const char * linphone_chat_message_get_text(const LinphoneChatMessage* message);
time_t linphone_chat_message_get_time(const LinphoneChatMessage* message);
void* linphone_chat_message_get_user_data(const LinphoneChatMessage* message);
void linphone_chat_message_set_user_data(LinphoneChatMessage* message,void*);
LinphoneChatRoom* linphone_chat_message_get_chat_room(LinphoneChatMessage *msg);
const LinphoneAddress* linphone_chat_message_get_peer_address(LinphoneChatMessage *msg);
LinphoneAddress *linphone_chat_message_get_local_address(const LinphoneChatMessage* message);
void linphone_chat_message_add_custom_header(LinphoneChatMessage* message, const char *header_name, const char *header_value);
const char * linphone_chat_message_get_custom_header(LinphoneChatMessage* message, const char *header_name);
/**
* @}
*/
@ -885,7 +860,8 @@ typedef enum _LinphoneFirewallPolicy{
LinphonePolicyNoFirewall,
LinphonePolicyUseNatAddress,
LinphonePolicyUseStun,
LinphonePolicyUseIce
LinphonePolicyUseIce,
LinphonePolicyUseUpnp,
} LinphoneFirewallPolicy;
typedef enum _LinphoneWaitingState{
@ -898,6 +874,35 @@ typedef void * (*LinphoneWaitingCallback)(struct _LinphoneCore *lc, void *contex
/* THE main API */
/**
* Define a log handler.
*
* @ingroup misc
*
* @param logfunc The function pointer of the log handler.
*/
void linphone_core_set_log_handler(OrtpLogFunc logfunc);
/**
* Define a log file.
*
* @ingroup misc
*
* If the file pointer passed as an argument is NULL, stdout is used instead.
*
* @param file A pointer to the FILE structure of the file to write to.
*/
void linphone_core_set_log_file(FILE *file);
/**
* Define the log level.
*
* @ingroup misc
*
* The loglevel parameter is a bitmask parameter. Therefore to enable only warning and error
* messages, use ORTP_WARNING | ORTP_ERROR. To disable logs, simply set loglevel to 0.
*
* @param loglevel A bitmask of the log levels to set.
*/
void linphone_core_set_log_level(OrtpLogLevel loglevel);
void linphone_core_enable_logs(FILE *file);
void linphone_core_enable_logs_with_cb(OrtpLogFunc logfunc);
void linphone_core_disable_logs(void);
@ -908,6 +913,20 @@ const char *linphone_core_get_user_agent_version(void);
LinphoneCore *linphone_core_new(const LinphoneCoreVTable *vtable,
const char *config_path, const char *factory_config, void* userdata);
/**
* Instantiates a LinphoneCore object with a given LpConfig.
* @ingroup initializing
*
* The LinphoneCore object is the primary handle for doing all phone actions.
* It should be unique within your application.
* @param vtable a LinphoneCoreVTable structure holding your application callbacks
* @param config a pointer to an LpConfig object holding the configuration of the LinphoneCore to be instantiated.
* @param userdata an opaque user pointer that can be retrieved at any time (for example in
* callbacks) using linphone_core_get_user_data().
* @see linphone_core_new
**/
LinphoneCore *linphone_core_new_with_config(const LinphoneCoreVTable *vtable, struct _LpConfig *config, void *userdata);
/* function to be periodically called in a main loop */
/* For ICE to work properly it should be called every 20ms */
void linphone_core_iterate(LinphoneCore *lc);
@ -976,7 +995,12 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho
int linphone_core_defer_call_update(LinphoneCore *lc, LinphoneCall *call);
int linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params);
/**
* @ingroup media_parameters
* Get default call parameters reflecting current linphone core configuration
* @param LinphoneCore object
* @return LinphoneCallParams
*/
LinphoneCallParams *linphone_core_create_default_call_parameters(LinphoneCore *lc);
LinphoneCall *linphone_core_get_call_by_remote_address(LinphoneCore *lc, const char *remote_address);
@ -1006,16 +1030,8 @@ int linphone_core_get_upload_bandwidth(const LinphoneCore *lc);
void linphone_core_enable_adaptive_rate_control(LinphoneCore *lc, bool_t enabled);
bool_t linphone_core_adaptive_rate_control_enabled(const LinphoneCore *lc);
/**
* set audio packetization time linphone expect to receive from peer
* @ingroup media_parameters
*
*/
void linphone_core_set_download_ptime(LinphoneCore *lc, int ptime);
/**
* get audio packetization time linphone expect to receive from peer, 0 means unspecified
* @ingroup media_parameters
*/
int linphone_core_get_download_ptime(LinphoneCore *lc);
void linphone_core_set_upload_ptime(LinphoneCore *lc, int ptime);
@ -1032,21 +1048,28 @@ const MSList *linphone_core_get_video_codecs(const LinphoneCore *lc);
int linphone_core_set_video_codecs(LinphoneCore *lc, MSList *codecs);
bool_t linphone_core_payload_type_enabled(LinphoneCore *lc, const PayloadType *pt);
/**
* Enable payload type
* @param linphone core
* @param pt payload type to enable, can be retrieve from #linphone_core_find_payload_type
* @param TRUE if enabled
* @return 0 if succed
*
*/
int linphone_core_enable_payload_type(LinphoneCore *lc, PayloadType *pt, bool_t enable);
/**
* Wildcard value used by #linphone_core_find_payload_type to ignore rate in search algirithm
* Wildcard value used by #linphone_core_find_payload_type to ignore rate in search algorithm
* @ingroup media_parameters
*/
#define LINPHONE_FIND_PAYLOAD_IGNORE_RATE -1
/**
* Wildcard value used by #linphone_core_find_payload_type to ignore channel in search algirithm
* Wildcard value used by #linphone_core_find_payload_type to ignore channel in search algorithm
* @ingroup media_parameters
*/
#define LINPHONE_FIND_PAYLOAD_IGNORE_CHANNELS -1
/**
* Get payload type from mime type and clock rate
* Get payload type from mime type and clock rate
* @ingroup media_parameters
* This function searches in audio and video codecs for the given payload type name and clockrate.
* @param lc #LinphoneCore object
@ -1164,10 +1187,43 @@ void linphone_core_set_in_call_timeout(LinphoneCore *lc, int seconds);
int linphone_core_get_in_call_timeout(LinphoneCore *lc);
void linphone_core_set_delayed_timeout(LinphoneCore *lc, int seconds);
int linphone_core_get_delayed_timeout(LinphoneCore *lc);
void linphone_core_set_stun_server(LinphoneCore *lc, const char *server);
const char * linphone_core_get_stun_server(const LinphoneCore *lc);
/**
* @ingroup network_parameters
* Return the availability of uPnP.
*
* @return true if uPnP is available otherwise return false.
*/
bool_t linphone_core_upnp_available();
/**
* @ingroup network_parameters
* Return the internal state of uPnP.
*
* @param lc #LinphoneCore
* @return an LinphoneUpnpState.
*/
LinphoneUpnpState linphone_core_get_upnp_state(const LinphoneCore *lc);
/**
* @ingroup network_parameters
* Return the external ip address of router.
* In some cases the uPnP can have an external ip address but not a usable uPnP
* (state different of Ok).
*
* @param lc #LinphoneCore
* @return a null terminated string containing the external ip address. If the
* the external ip address is not available return null.
*/
const char * linphone_core_get_upnp_external_ipaddress(const LinphoneCore *lc);
void linphone_core_set_nat_address(LinphoneCore *lc, const char *addr);
const char *linphone_core_get_nat_address(const LinphoneCore *lc);
@ -1298,6 +1354,17 @@ 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);
/**
* @brief Get the camera sensor rotation.
*
* This is needed on some mobile platforms to get the number of degrees the camera sensor
* is rotated relative to the screen.
*
* @param lc The linphone core related to the operation
* @return The camera sensor rotation in degrees (0 to 360) or -1 if it could not be retrieved
*/
int linphone_core_get_camera_sensor_rotation(LinphoneCore *lc);
/* start or stop streaming video in case of embedded window */
void linphone_core_show_video(LinphoneCore *lc, bool_t show);
@ -1386,7 +1453,13 @@ void linphone_core_refresh_registers(LinphoneCore* lc);
/* Path to the file storing secrets cache */
void linphone_core_set_zrtp_secrets_file(LinphoneCore *lc, const char* file);
const char *linphone_core_get_zrtp_secrets_file(LinphoneCore *lc);
/**
* Search from the list of current calls if a remote address match uri
* @ingroup call_control
* @param lc
* @param uri which should match call remote uri
* @return LinphoneCall or NULL is no match is found
*/
const LinphoneCall* linphone_core_find_call_from_uri(LinphoneCore *lc, const char *uri);
int linphone_core_add_to_conference(LinphoneCore *lc, LinphoneCall *call);
@ -1399,8 +1472,21 @@ float linphone_core_get_conference_local_input_volume(LinphoneCore *lc);
int linphone_core_terminate_conference(LinphoneCore *lc);
int linphone_core_get_conference_size(LinphoneCore *lc);
int linphone_core_start_conference_recording(LinphoneCore *lc, const char *path);
int linphone_core_stop_conference_recording(LinphoneCore *lc);
/**
* Get the maximum number of simultaneous calls Linphone core can manage at a time. All new call above this limit are declined with a busy answer
* @ingroup initializing
* @param lc core
* @return max number of simultaneous calls
*/
int linphone_core_get_max_calls(LinphoneCore *lc);
/**
* Set the maximum number of simultaneous calls Linphone core can manage at a time. All new call above this limit are declined with a busy answer
* @ingroup initializing
* @param lc core
* @param max number of simultaneous calls
*/
void linphone_core_set_max_calls(LinphoneCore *lc, int max);
bool_t linphone_core_sound_resources_locked(LinphoneCore *lc);
@ -1446,7 +1532,6 @@ void linphone_core_set_video_dscp(LinphoneCore *lc, int dscp);
int linphone_core_get_video_dscp(const LinphoneCore *lc);
#ifdef __cplusplus
}
#endif

View file

@ -532,10 +532,6 @@ extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_newLinphoneCore(JNIEnv*
,userConfig
,factoryConfig
,ldata);
//clear auth info list
linphone_core_clear_all_auth_info((LinphoneCore*) nativePtr);
//clear existing proxy config
linphone_core_clear_proxy_config((LinphoneCore*) nativePtr);
if (userConfig) env->ReleaseStringUTFChars(juserConfig, userConfig);
if (factoryConfig) env->ReleaseStringUTFChars(jfactoryConfig, factoryConfig);
@ -654,6 +650,13 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_terminateCall( JNIEnv*
linphone_core_terminate_call((LinphoneCore*)lc,(LinphoneCall*)call);
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_declineCall( JNIEnv* env
,jobject thiz
,jlong lc
,jlong call, jint reason) {
linphone_core_decline_call((LinphoneCore*)lc,(LinphoneCall*)call,(LinphoneReason)reason);
}
extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_getRemoteAddress( JNIEnv* env
,jobject thiz
,jlong lc) {
@ -993,10 +996,24 @@ extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_startEchoCalibration(JNI
,jobject data) {
return (jint)linphone_core_start_echo_calibration((LinphoneCore*)lc
, LinphoneCoreData::ecCalibrationStatus
, NULL
, NULL
, data?env->NewGlobalRef(data):NULL);
}
extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_needsEchoCalibration(JNIEnv *env, jobject thiz, jlong lc){
MSSndCard *sndcard;
MSSndCardManager *m=ms_snd_card_manager_get();
const char *card=linphone_core_get_capture_device((LinphoneCore*)lc);
sndcard=ms_snd_card_manager_get_card(m,card);
if (sndcard == NULL){
ms_error("Could not get soundcard.");
return TRUE;
}
return (ms_snd_card_get_capabilities(sndcard) & MS_SND_CARD_CAP_BUILTIN_ECHO_CANCELLER) || (ms_snd_card_get_minimal_latency(sndcard)>0);
}
extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getMediaEncryption(JNIEnv* env
,jobject thiz
,jlong lc
@ -1172,33 +1189,150 @@ extern "C" jboolean Java_org_linphone_core_LinphoneProxyConfigImpl_publishEnable
//Auth Info
extern "C" jlong Java_org_linphone_core_LinphoneAuthInfoImpl_newLinphoneAuthInfo(JNIEnv* env
, jobject thiz
, jstring jusername
, jstring juserid
, jstring jpassword
, jstring jha1
, jstring jrealm) {
const char* username = env->GetStringUTFChars(jusername, NULL);
const char* userid = env->GetStringUTFChars(juserid, NULL);
const char* password = env->GetStringUTFChars(jpassword, NULL);
const char* ha1 = env->GetStringUTFChars(jha1, NULL);
const char* realm = env->GetStringUTFChars(jrealm, NULL);
jlong auth = (jlong)linphone_auth_info_new(username,userid,password,ha1,realm);
env->ReleaseStringUTFChars(jusername, username);
env->ReleaseStringUTFChars(juserid, userid);
env->ReleaseStringUTFChars(jpassword, password);
env->ReleaseStringUTFChars(jha1, ha1);
env->ReleaseStringUTFChars(jrealm, realm);
return auth;
, jobject thiz ) {
return (jlong)linphone_auth_info_new(NULL,NULL,NULL,NULL,NULL);
}
extern "C" void Java_org_linphone_core_LinphoneAuthInfoImpl_delete(JNIEnv* env
, jobject thiz
, jlong ptr) {
linphone_auth_info_destroy((LinphoneAuthInfo*)ptr);
}
/*
* Class: org_linphone_core_LinphoneAuthInfoImpl
* Method: getPassword
* Signature: (J)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_getPassword
(JNIEnv *env , jobject, jlong auth_info) {
const char* passwd = linphone_auth_info_get_passwd((LinphoneAuthInfo*)auth_info);
if (passwd) {
return env->NewStringUTF(passwd);
} else {
return NULL;
}
}
/*
* Class: org_linphone_core_LinphoneAuthInfoImpl
* Method: getRealm
* Signature: (J)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_getRealm
(JNIEnv *env , jobject, jlong auth_info) {
const char* realm = linphone_auth_info_get_realm((LinphoneAuthInfo*)auth_info);
if (realm) {
return env->NewStringUTF(realm);
} else {
return NULL;
}
}
/*
* Class: org_linphone_core_LinphoneAuthInfoImpl
* Method: getUsername
* Signature: (J)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_getUsername
(JNIEnv *env , jobject, jlong auth_info) {
const char* username = linphone_auth_info_get_username((LinphoneAuthInfo*)auth_info);
if (username) {
return env->NewStringUTF(username);
} else {
return NULL;
}
}
/*
* Class: org_linphone_core_LinphoneAuthInfoImpl
* Method: setPassword
* Signature: (JLjava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_setPassword
(JNIEnv *env, jobject, jlong auth_info, jstring jpassword) {
const char* password = jpassword?env->GetStringUTFChars(jpassword, NULL):NULL;
linphone_auth_info_set_passwd((LinphoneAuthInfo*)auth_info,password);
if (password) env->ReleaseStringUTFChars(jpassword, password);
}
/*
* Class: org_linphone_core_LinphoneAuthInfoImpl
* Method: setRealm
* Signature: (JLjava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_setRealm
(JNIEnv *env, jobject, jlong auth_info, jstring jrealm) {
const char* realm = jrealm?env->GetStringUTFChars(jrealm, NULL):NULL;
linphone_auth_info_set_realm((LinphoneAuthInfo*)auth_info,realm);
if (realm) env->ReleaseStringUTFChars(jrealm, realm);
}
/*
* Class: org_linphone_core_LinphoneAuthInfoImpl
* Method: setUsername
* Signature: (JLjava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_setUsername
(JNIEnv *env, jobject, jlong auth_info, jstring jusername) {
const char* username = jusername?env->GetStringUTFChars(jusername, NULL):NULL;
linphone_auth_info_set_username((LinphoneAuthInfo*)auth_info,username);
if (username) env->ReleaseStringUTFChars(jusername, username);
}
/*
* Class: org_linphone_core_LinphoneAuthInfoImpl
* Method: setAuthUserId
* Signature: (JLjava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_setUserId
(JNIEnv *env, jobject, jlong auth_info, jstring juserid) {
const char* userid = juserid?env->GetStringUTFChars(juserid, NULL):NULL;
linphone_auth_info_set_userid((LinphoneAuthInfo*)auth_info,userid);
if (userid) env->ReleaseStringUTFChars(juserid, userid);
}
/*
* Class: org_linphone_core_LinphoneAuthInfoImpl
* Method: getAuthUserId
* Signature: (J)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_getUserId
(JNIEnv *env , jobject, jlong auth_info) {
const char* userid = linphone_auth_info_get_userid((LinphoneAuthInfo*)auth_info);
if (userid) {
return env->NewStringUTF(userid);
} else {
return NULL;
}
}
/*
* Class: org_linphone_core_LinphoneAuthInfoImpl
* Method: setHa1
* Signature: (JLjava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_setHa1
(JNIEnv *env, jobject, jlong auth_info, jstring jha1) {
const char* ha1 = jha1?env->GetStringUTFChars(jha1, NULL):NULL;
linphone_auth_info_set_ha1((LinphoneAuthInfo*)auth_info,ha1);
if (ha1) env->ReleaseStringUTFChars(jha1, ha1);
}
/*
* Class: org_linphone_core_LinphoneAuthInfoImpl
* Method: getHa1
* Signature: (J)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_getHa1
(JNIEnv *env , jobject, jlong auth_info) {
const char* ha1 = linphone_auth_info_get_ha1((LinphoneAuthInfo*)auth_info);
if (ha1) {
return env->NewStringUTF(ha1);
} else {
return NULL;
}
}
//LinphoneAddress
@ -1253,7 +1387,14 @@ extern "C" jstring Java_org_linphone_core_LinphoneAddressImpl_getDomain(JNIEnv*
return NULL;
}
}
extern "C" void Java_org_linphone_core_LinphoneAddressImpl_setDomain(JNIEnv* env
,jobject thiz
,jlong ptr
,jstring jdomain) {
const char* domain = env->GetStringUTFChars(jdomain, NULL);
linphone_address_set_domain((LinphoneAddress*)ptr, domain);
env->ReleaseStringUTFChars(jdomain, domain);
}
extern "C" jstring Java_org_linphone_core_LinphoneAddressImpl_toString(JNIEnv* env
,jobject thiz
,jlong ptr) {
@ -1367,7 +1508,7 @@ extern "C" jfloat Java_org_linphone_core_LinphoneCallStatsImpl_getReceiverLossRa
}
extern "C" jfloat Java_org_linphone_core_LinphoneCallStatsImpl_getSenderInterarrivalJitter(JNIEnv *env, jobject thiz, jlong stats_ptr, jlong call_ptr) {
LinphoneCallStats *stats = (LinphoneCallStats *)stats_ptr;
const LinphoneCall *call = (LinphoneCall *)call_ptr;
LinphoneCall *call = (LinphoneCall *)call_ptr;
const LinphoneCallParams *params;
const PayloadType *pt;
const report_block_t *srb = NULL;
@ -1396,7 +1537,7 @@ extern "C" jfloat Java_org_linphone_core_LinphoneCallStatsImpl_getSenderInterarr
}
extern "C" jfloat Java_org_linphone_core_LinphoneCallStatsImpl_getReceiverInterarrivalJitter(JNIEnv *env, jobject thiz, jlong stats_ptr, jlong call_ptr) {
LinphoneCallStats *stats = (LinphoneCallStats *)stats_ptr;
const LinphoneCall *call = (LinphoneCall *)call_ptr;
LinphoneCall *call = (LinphoneCall *)call_ptr;
const LinphoneCallParams *params;
const PayloadType *pt;
const report_block_t *rrb = NULL;
@ -1446,6 +1587,23 @@ extern "C" jfloat Java_org_linphone_core_LinphoneCallStatsImpl_getJitterBufferSi
return (jfloat)((LinphoneCallStats *)stats_ptr)->jitter_stats.jitter_buffer_size_ms;
}
extern "C" jfloat Java_org_linphone_core_LinphoneCallStatsImpl_getLocalLossRate(JNIEnv *env, jobject thiz,jlong stats_ptr) {
const LinphoneCallStats *stats = (LinphoneCallStats *)stats_ptr;
return stats->local_loss_rate;
}
extern "C" jfloat Java_org_linphone_core_LinphoneCallStatsImpl_getLocalLateRate(JNIEnv *env, jobject thiz, jlong stats_ptr) {
const LinphoneCallStats *stats = (LinphoneCallStats *)stats_ptr;
return stats->local_late_rate;
}
extern "C" void Java_org_linphone_core_LinphoneCallStatsImpl_updateStats(JNIEnv *env, jobject thiz, jlong call_ptr, jint mediatype) {
if (mediatype==LINPHONE_CALL_STATS_AUDIO)
linphone_call_get_audio_stats((LinphoneCall*)call_ptr);
else
linphone_call_get_video_stats((LinphoneCall*)call_ptr);
}
/*payloadType*/
extern "C" jstring Java_org_linphone_core_PayloadTypeImpl_toString(JNIEnv* env,jobject thiz,jlong ptr) {
PayloadType* pt = (PayloadType*)ptr;
@ -1508,7 +1666,17 @@ extern "C" jlong Java_org_linphone_core_LinphoneCallImpl_getRemoteAddress( JNIEn
extern "C" jstring Java_org_linphone_core_LinphoneCallImpl_getRemoteUserAgent(JNIEnv *env, jobject thiz, jlong ptr) {
LinphoneCall *call = (LinphoneCall *)ptr;
jstring jvalue = env->NewStringUTF(linphone_call_get_remote_user_agent(call));
const char *value=linphone_call_get_remote_user_agent(call);
jstring jvalue=NULL;
if (value) jvalue=env->NewStringUTF(value);
return jvalue;
}
extern "C" jstring Java_org_linphone_core_LinphoneCallImpl_getRemoteContact(JNIEnv *env, jobject thiz, jlong ptr) {
LinphoneCall *call = (LinphoneCall *)ptr;
const char *value=linphone_call_get_remote_contact(call);
jstring jvalue = NULL;
if (value) jvalue=env->NewStringUTF(value);
return jvalue;
}
@ -1560,7 +1728,6 @@ extern "C" jfloat Java_org_linphone_core_LinphoneCallImpl_getAverageQuality( JNI
return (jfloat)linphone_call_get_average_quality((LinphoneCall*)ptr);
}
//LinphoneFriend
extern "C" jlong Java_org_linphone_core_LinphoneFriendImpl_newLinphoneFriend(JNIEnv* env
,jobject thiz
@ -1661,12 +1828,32 @@ extern "C" void Java_org_linphone_core_LinphoneChatMessageImpl_setUserData(JNIEn
jobject ud = env->NewGlobalRef(thiz);
linphone_chat_message_set_user_data((LinphoneChatMessage*)ptr,(void*) ud);
}
extern "C" jstring Java_org_linphone_core_LinphoneChatMessageImpl_getMessage(JNIEnv* env
extern "C" jstring Java_org_linphone_core_LinphoneChatMessageImpl_getText(JNIEnv* env
,jobject thiz
,jlong ptr) {
jstring jvalue =env->NewStringUTF(linphone_chat_message_get_message((LinphoneChatMessage*)ptr));
jstring jvalue =env->NewStringUTF(linphone_chat_message_get_text((LinphoneChatMessage*)ptr));
return jvalue;
}
extern "C" jstring Java_org_linphone_core_LinphoneChatMessageImpl_getCustomHeader(JNIEnv* env
,jobject thiz
,jlong ptr, jstring jheader_name) {
const char *name=env->GetStringUTFChars(jheader_name,NULL);
const char *value=linphone_chat_message_get_custom_header((LinphoneChatMessage*)ptr,name);
env->ReleaseStringUTFChars(jheader_name, name);
return value ? env->NewStringUTF(value) : NULL;
}
extern "C" void Java_org_linphone_core_LinphoneChatMessageImpl_addCustomHeader(JNIEnv* env
,jobject thiz
,jlong ptr, jstring jheader_name, jstring jheader_value) {
const char *name=env->GetStringUTFChars(jheader_name,NULL);
const char *value=env->GetStringUTFChars(jheader_value,NULL);
linphone_chat_message_add_custom_header((LinphoneChatMessage*)ptr,name,value);
env->ReleaseStringUTFChars(jheader_name, name);
env->ReleaseStringUTFChars(jheader_value, value);
}
extern "C" jstring Java_org_linphone_core_LinphoneChatMessageImpl_getExternalBodyUrl(JNIEnv* env
,jobject thiz
,jlong ptr) {
@ -1686,11 +1873,19 @@ extern "C" jlong Java_org_linphone_core_LinphoneChatMessageImpl_getFrom(JNIEnv*
,jlong ptr) {
return (jlong) linphone_chat_message_get_from((LinphoneChatMessage*)ptr);
}
extern "C" jlong Java_org_linphone_core_LinphoneChatMessageImpl_getPeerAddress(JNIEnv* env
,jobject thiz
,jlong ptr) {
return (jlong) linphone_chat_message_get_peer_address((LinphoneChatMessage*)ptr);
}
extern "C" jlong Java_org_linphone_core_LinphoneChatMessageImpl_getTime(JNIEnv* env
,jobject thiz
,jlong ptr) {
return (jlong) linphone_chat_message_get_time((LinphoneChatMessage*)ptr);
}
extern "C" void Java_org_linphone_core_LinphoneChatRoomImpl_sendMessage(JNIEnv* env
,jobject thiz
,jlong ptr
@ -1837,6 +2032,29 @@ extern "C" jboolean Java_org_linphone_core_LinphoneCallParamsImpl_localConferenc
return (jboolean)linphone_call_params_local_conference_mode((LinphoneCallParams*)lcp);
}
extern "C" jstring Java_org_linphone_core_LinphoneCallParamsImpl_getCustomHeader(JNIEnv *env, jobject thiz, jlong lcp, jstring jheader_name){
const char* header_name=env->GetStringUTFChars(jheader_name, NULL);
const char *header_value=linphone_call_params_get_custom_header((LinphoneCallParams*)lcp,header_name);
env->ReleaseStringUTFChars(jheader_name, header_name);
return header_value ? env->NewStringUTF(header_value) : NULL;
}
extern "C" void Java_org_linphone_core_LinphoneCallParamsImpl_addCustomHeader(JNIEnv *env, jobject thiz, jlong lcp, jstring jheader_name, jstring jheader_value){
const char* header_name=env->GetStringUTFChars(jheader_name, NULL);
const char* header_value=env->GetStringUTFChars(jheader_value, NULL);
linphone_call_params_add_custom_header((LinphoneCallParams*)lcp,header_name,header_value);
env->ReleaseStringUTFChars(jheader_name, header_name);
env->ReleaseStringUTFChars(jheader_value, header_value);
}
extern "C" void Java_org_linphone_core_LinphoneCallParamsImpl_setRecordFile(JNIEnv *env, jobject thiz, jlong lcp, jstring jrecord_file){
if (jrecord_file){
const char* record_file=env->GetStringUTFChars(jrecord_file, NULL);
linphone_call_params_set_record_file((LinphoneCallParams*)lcp,record_file);
env->ReleaseStringUTFChars(jrecord_file, record_file);
}else linphone_call_params_set_record_file((LinphoneCallParams*)lcp,NULL);
}
extern "C" void Java_org_linphone_core_LinphoneCallParamsImpl_destroy(JNIEnv *env, jobject thiz, jlong lc){
return linphone_call_params_destroy((LinphoneCallParams*)lc);
}
@ -1863,6 +2081,14 @@ extern "C" jboolean Java_org_linphone_core_LinphoneCallImpl_cameraEnabled(JNIEnv
return (jboolean)linphone_call_camera_enabled((LinphoneCall *)lc);
}
extern "C" void Java_org_linphone_core_LinphoneCallImpl_startRecording(JNIEnv *env, jobject thiz, jlong lc){
linphone_call_start_recording((LinphoneCall *)lc);
}
extern "C" void Java_org_linphone_core_LinphoneCallImpl_stopRecording(JNIEnv *env, jobject thiz, jlong lc){
linphone_call_stop_recording((LinphoneCall *)lc);
}
extern "C" jobject Java_org_linphone_core_LinphoneCoreImpl_inviteAddressWithParams(JNIEnv *env, jobject thiz, jlong lc, jlong addr, jlong params){
LinphoneCoreData *lcd=(LinphoneCoreData*)linphone_core_get_user_data((LinphoneCore*)lc);
return lcd->getCall(env,linphone_core_invite_address_with_params((LinphoneCore *)lc, (const LinphoneAddress *)addr, (const LinphoneCallParams *)params));
@ -1926,6 +2152,14 @@ extern "C" jint Java_org_linphone_core_LinphoneCallImpl_getDuration(JNIEnv* env
return (jint)linphone_call_get_duration((LinphoneCall *) ptr);
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setSipDscp(JNIEnv* env,jobject thiz,jlong ptr, jint dscp){
linphone_core_set_sip_dscp((LinphoneCore*)ptr,dscp);
}
extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getSipDscp(JNIEnv* env,jobject thiz,jlong ptr){
return linphone_core_get_sip_dscp((LinphoneCore*)ptr);
}
extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getSignalingTransportPort(JNIEnv* env,jobject thiz,jlong ptr, jint code) {
LCSipTransports tr;
linphone_core_get_sip_transports((LinphoneCore *) ptr, &tr);
@ -1982,9 +2216,11 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_leaveConference(JNIEnv *
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_addAllToConference(JNIEnv *env,jobject thiz,jlong pCore) {
linphone_core_add_all_to_conference((LinphoneCore *) pCore);
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_addToConference(JNIEnv *env,jobject thiz,jlong pCore, jlong pCall) {
linphone_core_add_to_conference((LinphoneCore *) pCore, (LinphoneCall *) pCall);
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_removeFromConference(JNIEnv *env,jobject thiz,jlong pCore, jlong pCall) {
linphone_core_remove_from_conference((LinphoneCore *) pCore, (LinphoneCall *) pCall);
}
@ -1995,6 +2231,22 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_terminateConference(JNIE
extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getConferenceSize(JNIEnv *env,jobject thiz,jlong pCore) {
return (jint)linphone_core_get_conference_size((LinphoneCore *) pCore);
}
extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_startConferenceRecording(JNIEnv *env,jobject thiz,jlong pCore, jstring jpath){
int err=-1;
if (jpath){
const char *path=env->GetStringUTFChars(jpath, NULL);
err=linphone_core_start_conference_recording((LinphoneCore*)pCore,path);
env->ReleaseStringUTFChars(jpath,path);
}
return err;
}
extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_stopConferenceRecording(JNIEnv *env,jobject thiz,jlong pCore){
int err=linphone_core_stop_conference_recording((LinphoneCore*)pCore);
return err;
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_terminateAllCalls(JNIEnv *env,jobject thiz,jlong pCore) {
linphone_core_terminate_all_calls((LinphoneCore *) pCore);
}
@ -2212,6 +2464,22 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setVideoPortRange(JNIEnv
linphone_core_set_video_port_range((LinphoneCore *)lc, min_port, max_port);
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setAudioDscp(JNIEnv* env,jobject thiz,jlong ptr, jint dscp){
linphone_core_set_audio_dscp((LinphoneCore*)ptr,dscp);
}
extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getAudioDscp(JNIEnv* env,jobject thiz,jlong ptr){
return linphone_core_get_audio_dscp((LinphoneCore*)ptr);
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setVideoDscp(JNIEnv* env,jobject thiz,jlong ptr, jint dscp){
linphone_core_set_video_dscp((LinphoneCore*)ptr,dscp);
}
extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getVideoDscp(JNIEnv* env,jobject thiz,jlong ptr){
return linphone_core_get_video_dscp((LinphoneCore*)ptr);
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setIncomingTimeout(JNIEnv *env, jobject thiz, jlong lc, jint timeout) {
linphone_core_set_inc_timeout((LinphoneCore *)lc, timeout);
}
@ -2229,6 +2497,36 @@ extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_getConfig(JNIEnv *env,
return (jlong) linphone_core_get_config((LinphoneCore *)lc);
}
extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_upnpAvailable(JNIEnv *env, jobject thiz, jlong lc) {
return (jboolean) linphone_core_upnp_available();
}
extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getUpnpState(JNIEnv *env, jobject thiz, jlong lc) {
return (jint) linphone_core_get_upnp_state((LinphoneCore *)lc);
}
extern "C" jstring Java_org_linphone_core_LinphoneCoreImpl_getUpnpExternalIpaddress(JNIEnv *env, jobject thiz, jlong lc) {
jstring jvalue = env->NewStringUTF(linphone_core_get_upnp_external_ipaddress((LinphoneCore *)lc));
return jvalue;
}
extern "C" jlong Java_org_linphone_core_LpConfigImpl_newLpConfigImpl(JNIEnv *env, jobject thiz, jstring file) {
const char *cfile = env->GetStringUTFChars(file, NULL);
LpConfig *lp = lp_config_new(cfile);
env->ReleaseStringUTFChars(file, cfile);
return (jlong) lp;
}
extern "C" void Java_org_linphone_core_LpConfigImpl_sync(JNIEnv *env, jobject thiz, jlong lpc) {
LpConfig *lp = (LpConfig *)lpc;
lp_config_sync(lp);
}
extern "C" void Java_org_linphone_core_LpConfigImpl_delete(JNIEnv *env, jobject thiz, jlong lpc) {
LpConfig *lp = (LpConfig *)lpc;
lp_config_destroy(lp);
}
extern "C" void Java_org_linphone_core_LpConfigImpl_setInt(JNIEnv *env, jobject thiz, jlong lpc,
jstring section, jstring key, jint value) {
const char *csection = env->GetStringUTFChars(section, NULL);

View file

@ -64,12 +64,15 @@ typedef enum {
typedef void (*LinphoneEcCalibrationCallback)(LinphoneCore *lc, LinphoneEcCalibratorStatus status, int delay_ms, void *data);
typedef void (*LinphoneEcCalibrationAudioInit)(void *data);
typedef void (*LinphoneEcCalibrationAudioUninit)(void *data);
/**
*
* Start an echo calibration of the sound devices, in order to find adequate settings for the echo canceller automatically.
**/
int linphone_core_start_echo_calibration(LinphoneCore *lc, LinphoneEcCalibrationCallback cb, void *cb_data);
int linphone_core_start_echo_calibration(LinphoneCore *lc, LinphoneEcCalibrationCallback cb,
LinphoneEcCalibrationAudioInit audio_init_cb, LinphoneEcCalibrationAudioUninit audio_uninit_cb, void *cb_data);
/**
* @ingroup IOS
* Special function to warm up dtmf feeback stream. #linphone_core_stop_dtmf_stream must() be called before entering FG mode

View file

@ -132,6 +132,13 @@ void linphone_friend_destroy(LinphoneFriend *lf);
*/
int linphone_friend_set_addr(LinphoneFriend *fr, const LinphoneAddress* address);
/**
* set the display name for this friend
* @param lf #LinphoneFriend object
* @param name
*/
int linphone_friend_set_name(LinphoneFriend *lf, const char *name);
/**
* get address of this friend
* @param lf #LinphoneFriend object

View file

@ -190,6 +190,7 @@ void lp_config_parse(LpConfig *lpconfig, FILE *file){
if (pos2-pos1>=0){
/* found a pair key,value */
if (cur!=NULL){
LpItem *item=lp_section_find_item(cur,key);
if (item==NULL){
@ -198,7 +199,7 @@ void lp_config_parse(LpConfig *lpconfig, FILE *file){
ms_free(item->value);
item->value=strdup(pos1);
}
/*printf("Found %s %s={%s}\n",cur->name,key,pos1);*/
/*ms_message("Found %s=%s",key,pos1);*/
}else{
ms_warning("found key,item but no sections");
}
@ -210,30 +211,42 @@ void lp_config_parse(LpConfig *lpconfig, FILE *file){
}
LpConfig * lp_config_new(const char *filename){
return lp_config_new_with_factory(filename, NULL);
}
LpConfig *lp_config_new_with_factory(const char *config_filename, const char *factory_config_filename) {
LpConfig *lpconfig=lp_new0(LpConfig,1);
if (filename!=NULL){
lpconfig->filename=ortp_strdup(filename);
lpconfig->file=fopen(filename,"rw");
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+");
if (lpconfig->file!=NULL){
struct stat fileStat;
lp_config_parse(lpconfig,lpconfig->file);
fclose(lpconfig->file);
fclose(lpconfig->file);
#if !defined(_WIN32_WCE)
/* make existing configuration files non-group/world-accessible */
if (chmod(filename, S_IRUSR | S_IWUSR) == -1)
ms_warning("unable to correct permissions on "
"configuration file: %s",
strerror(errno));
if ((stat(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_WCE*/
lpconfig->file=NULL;
lpconfig->modified=0;
}
}
if (factory_config_filename != NULL) {
lp_config_read_file(lpconfig, factory_config_filename);
}
return lpconfig;
}
int lp_config_read_file(LpConfig *lpconfig, const char *filename){
FILE* f=fopen(filename,"r");
if (f!=NULL){
ms_message("Reading config information from %s", filename);
lp_config_parse(lpconfig,f);
fclose(f);
return 0;

View file

@ -65,7 +65,29 @@ extern "C" {
(config) ? (lp_config_get_float(config, "default_values", name, default)) : (default)
/**
* Instantiates a LpConfig object from a user config file.
*
* @ingroup misc
* @param filename the filename of the config file to read to fill the instantiated LpConfig
* @see lp_config_new_with_factory
*/
LpConfig * lp_config_new(const char *filename);
/**
* Instantiates a LpConfig object from a user config file and a factory config file.
*
* @ingroup misc
* @param config_filename the filename of the user config file to read to fill the instantiated LpConfig
* @param factory_config_filename the filename of the factory config file to read to fill the instantiated LpConfig
* @see lp_config_new
*
* The user config file is read first to fill the LpConfig and then the factory config file is read.
* Therefore the configuration parameters defined in the user config file will be overwritten by the parameters
* defined in the factory config file.
*/
LpConfig * lp_config_new_with_factory(const char *config_filename, const char *factory_config_filename);
int lp_config_read_file(LpConfig *lpconfig, const char *filename);
/**
* Retrieves a configuration item as a string, given its section, key, and default value.

254
coreapi/message_storage.c Normal file
View file

@ -0,0 +1,254 @@
/*
message_storage.c
Copyright (C) 2012 Belledonne Communications, Grenoble, France
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "private.h"
#include "linphonecore.h"
#ifdef WIN32
static inline char *my_ctime_r(const time_t *t, char *buf){
strcpy(buf,ctime(t));
return buf;
}
#else
#define my_ctime_r ctime_r
#endif
#ifdef MSG_STORAGE_ENABLED
#include "sqlite3.h"
static const char *days[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
static const char *months[]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
static void create_chat_message(char **argv, void *data){
LinphoneChatRoom *cr = (LinphoneChatRoom *)data;
LinphoneChatMessage* new_message = linphone_chat_room_create_message(cr,argv[4]);
LinphoneAddress *from;
struct tm ret={0};
char tmp1[80]={0};
char tmp2[80]={0};
if(atoi(argv[3])==LinphoneChatMessageIncoming){
from=linphone_address_new(argv[2]);
} else {
from=linphone_address_new(argv[1]);
}
linphone_chat_message_set_from(new_message,from);
linphone_address_destroy(from);
if(argv[5]!=NULL){
int i,j;
sscanf(argv[5],"%3c %3c%d%d:%d:%d %d",tmp1,tmp2,&ret.tm_mday,
&ret.tm_hour,&ret.tm_min,&ret.tm_sec,&ret.tm_year);
ret.tm_year-=1900;
for(i=0;i<7;i++) {
if(strcmp(tmp1,days[i])==0) ret.tm_wday=i;
}
for(j=0;j<12;j++) {
if(strcmp(tmp2,months[j])==0) ret.tm_mon=j;
}
ret.tm_isdst=-1;
}
new_message->time=argv[5]!=NULL ? mktime(&ret) : time(NULL);
new_message->state=atoi(argv[7]);
cr->messages_hist=ms_list_prepend(cr->messages_hist,new_message);
}
static int callback(void *data, int argc, char **argv, char **colName){
create_chat_message(argv,data);
return 0;
}
void linphone_sql_request_message(sqlite3 *db,const char *stmt,LinphoneChatRoom *cr){
char* errmsg=NULL;
int ret;
ret=sqlite3_exec(db,stmt,callback,cr,&errmsg);
if(ret != SQLITE_OK) {
ms_error("Error in creation: %s.\n", errmsg);
sqlite3_free(errmsg);
}
}
void linphone_sql_request(sqlite3* db,const char *stmt){
char* errmsg=NULL;
int ret;
ret=sqlite3_exec(db,stmt,0,0,&errmsg);
if(ret != SQLITE_OK) {
ms_error("linphone_sql_request: error sqlite3_exec(): %s.\n", errmsg);
sqlite3_free(errmsg);
}
}
void linphone_chat_message_store(LinphoneChatMessage *msg){
LinphoneCore *lc=linphone_chat_room_get_lc(msg->chat_room);
if (lc->db){
char *peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(msg->chat_room));
char *local_contact=linphone_address_as_string_uri_only(linphone_chat_message_get_local_address(msg));
char datebuf[26];
char *buf=sqlite3_mprintf("insert into history values(NULL,%Q,%Q,%i,%Q,%Q,%i,%i);",
local_contact,peer,msg->dir,msg->message,my_ctime_r(&msg->time,datebuf),msg->is_read,msg->state);
linphone_sql_request(lc->db,buf);
sqlite3_free(buf);
ms_free(local_contact);
ms_free(peer);
}
}
void linphone_chat_message_store_state(LinphoneChatMessage *msg){
LinphoneCore *lc=msg->chat_room->lc;
if (lc->db){
char time_str[26];
char *buf=sqlite3_mprintf("update history set status=%i where message = %Q and time = %Q;",
msg->state,msg->message,my_ctime_r(&msg->time,time_str));
linphone_sql_request(lc->db,buf);
sqlite3_free(buf);
}
}
void linphone_chat_room_mark_as_read(LinphoneChatRoom *cr){
LinphoneCore *lc=linphone_chat_room_get_lc(cr);
int read=1;
if (lc->db==NULL) return ;
char *peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr));
char *buf=sqlite3_mprintf("update history set read=%i where remoteContact = %Q;",
read,peer);
linphone_sql_request(lc->db,buf);
sqlite3_free(buf);
ms_free(peer);
}
int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr){
LinphoneCore *lc=linphone_chat_room_get_lc(cr);
int numrows=0;
if (lc->db==NULL) return 0;
char *peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr));
char *buf=sqlite3_mprintf("select count(*) from history where remoteContact = %Q and read = 0;",peer);
sqlite3_stmt *selectStatement;
int returnValue = sqlite3_prepare_v2(lc->db,buf,-1,&selectStatement,NULL);
if (returnValue == SQLITE_OK){
if(sqlite3_step(selectStatement) == SQLITE_ROW){
numrows= sqlite3_column_int(selectStatement, 0);
}
}
sqlite3_finalize(selectStatement);
sqlite3_free(buf);
ms_free(peer);
return numrows;
}
void linphone_chat_room_delete_history(LinphoneChatRoom *cr){
LinphoneCore *lc=cr->lc;
if (lc->db==NULL) return ;
char *peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr));
char *buf=sqlite3_mprintf("delete from history where remoteContact = %Q;",peer);
linphone_sql_request(lc->db,buf);
sqlite3_free(buf);
ms_free(peer);
}
MSList *linphone_chat_room_get_history(LinphoneChatRoom *cr,int nb_message){
LinphoneCore *lc=linphone_chat_room_get_lc(cr);
MSList *ret;
if (lc->db==NULL) return NULL;
char *peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr));
cr->messages_hist = NULL;
char *buf=sqlite3_mprintf("select * from history where remoteContact = %Q order by id DESC limit %i ;",peer,nb_message);
linphone_sql_request_message(lc->db,buf,cr);
sqlite3_free(buf);
ret=cr->messages_hist;
cr->messages_hist=NULL;
ms_free(peer);
return ret;
}
void linphone_close_storage(sqlite3* db){
sqlite3_close(db);
}
void linphone_create_table(sqlite3* db){
char* errmsg=NULL;
int ret;
ret=sqlite3_exec(db,"CREATE TABLE if not exists history (id INTEGER PRIMARY KEY AUTOINCREMENT, localContact TEXT NOT NULL, remoteContact TEXT NOT NULL, direction INTEGER, message TEXT, time TEXT NOT NULL, read INTEGER, status INTEGER);",
0,0,&errmsg);
if(ret != SQLITE_OK) {
ms_error("Error in creation: %s.\n", errmsg);
sqlite3_free(errmsg);
}
}
void linphone_core_message_storage_init(LinphoneCore *lc){
int ret;
const char *errmsg;
sqlite3 *db;
ret=sqlite3_open(lc->chat_db_file,&db);
if(ret != SQLITE_OK) {
errmsg=sqlite3_errmsg(db);
ms_error("Error in the opening: %s.\n", errmsg);
sqlite3_close(db);
}
linphone_create_table(db);
lc->db=db;
}
void linphone_core_message_storage_close(LinphoneCore *lc){
if (lc->db){
sqlite3_close(lc->db);
lc->db=NULL;
}
}
#else
void linphone_chat_message_store(LinphoneChatMessage *cr){
}
void linphone_chat_message_store_state(LinphoneChatMessage *cr){
}
void linphone_chat_room_mark_as_read(LinphoneChatRoom *cr){
}
MSList *linphone_chat_room_get_history(LinphoneChatRoom *cr,int nb_message){
return NULL;
}
void linphone_chat_room_delete_history(LinphoneChatRoom *cr){
}
void linphone_core_message_storage_init(LinphoneCore *lc){
}
void linphone_core_message_storage_close(LinphoneCore *lc){
}
int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr){
return 0;
}
#endif

View file

@ -43,7 +43,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <net/if.h>
#include <ifaddrs.h>
#endif
#include <math.h>
#if !defined(WIN32)
@ -234,17 +234,26 @@ static int get_codec_bitrate(LinphoneCore *lc, const PayloadType *pt){
return pt->normal_bitrate;
}
/*
*((codec-birate*ptime/8) + RTP header + UDP header + IP header)*8/ptime;
*ptime=1/npacket
*/
static double get_audio_payload_bandwidth(LinphoneCore *lc, const PayloadType *pt){
double npacket=50;
double packet_size;
int bitrate;
if (strcmp(payload_type_get_mime(&payload_type_aaceld_44k), payload_type_get_mime(pt))==0) {
/*special case of aac 44K because ptime= 10ms*/
npacket=100;
}
bitrate=get_codec_bitrate(lc,pt);
packet_size= (((double)bitrate)/(50*8))+UDP_HDR_SZ+RTP_HDR_SZ+IP4_HDR_SZ;
packet_size= (((double)bitrate)/(npacket*8))+UDP_HDR_SZ+RTP_HDR_SZ+IP4_HDR_SZ;
return packet_size*8.0*npacket;
}
void linphone_core_update_allocated_audio_bandwidth_in_call(LinphoneCall *call, const PayloadType *pt){
call->audio_bw=(int)(get_audio_payload_bandwidth(call->core,pt)/1000.0);
call->audio_bw=(int)(ceil(get_audio_payload_bandwidth(call->core,pt)/1000.0)); /*rounding codec bandwidth should be avoid, specially for AMR*/
ms_message("Audio bandwidth for this call is %i",call->audio_bw);
}
@ -734,7 +743,7 @@ void linphone_core_update_local_media_description_from_ice(SalMediaDescription *
}
strncpy(desc->ice_pwd, ice_session_local_pwd(session), sizeof(desc->ice_pwd));
strncpy(desc->ice_ufrag, ice_session_local_ufrag(session), sizeof(desc->ice_ufrag));
for (i = 0; i < desc->nstreams; i++) {
for (i = 0; i < desc->n_active_streams; i++) {
SalStreamDescription *stream = &desc->streams[i];
IceCheckList *cl = ice_session_check_list(session, i);
nb_candidates = 0;
@ -838,7 +847,7 @@ void linphone_core_update_ice_from_remote_media_description(LinphoneCall *call,
ice_session_restart(call->ice_session);
ice_restarted = TRUE;
} else {
for (i = 0; i < md->nstreams; i++) {
for (i = 0; i < md->n_total_streams; i++) {
const SalStreamDescription *stream = &md->streams[i];
IceCheckList *cl = ice_session_check_list(call->ice_session, i);
if (cl && (strcmp(stream->rtp_addr, "0.0.0.0") == 0)) {
@ -857,7 +866,7 @@ void linphone_core_update_ice_from_remote_media_description(LinphoneCall *call,
}
ice_session_set_remote_credentials(call->ice_session, md->ice_ufrag, md->ice_pwd);
}
for (i = 0; i < md->nstreams; i++) {
for (i = 0; i < md->n_total_streams; i++) {
const SalStreamDescription *stream = &md->streams[i];
IceCheckList *cl = ice_session_check_list(call->ice_session, i);
if (cl && (stream->ice_pwd[0] != '\0') && (stream->ice_ufrag[0] != '\0')) {
@ -873,10 +882,10 @@ void linphone_core_update_ice_from_remote_media_description(LinphoneCall *call,
}
/* Create ICE check lists if needed and parse ICE attributes. */
for (i = 0; i < md->nstreams; i++) {
for (i = 0; i < md->n_total_streams; i++) {
const SalStreamDescription *stream = &md->streams[i];
IceCheckList *cl = ice_session_check_list(call->ice_session, i);
if (cl == NULL) {
if ((cl == NULL) && (i < md->n_active_streams)) {
cl = ice_check_list_new();
ice_session_add_check_list(call->ice_session, cl);
switch (stream->type) {
@ -930,7 +939,7 @@ void linphone_core_update_ice_from_remote_media_description(LinphoneCall *call,
}
}
}
for (i = ice_session_nb_check_lists(call->ice_session); i > md->nstreams; i--) {
for (i = ice_session_nb_check_lists(call->ice_session); i > md->n_active_streams; i--) {
ice_session_remove_check_list(call->ice_session, ice_session_check_list(call->ice_session, i - 1));
}
ice_session_check_mismatch(call->ice_session);
@ -948,8 +957,8 @@ bool_t linphone_core_media_description_contains_video_stream(const SalMediaDescr
{
int i;
for (i = 0; i < md->nstreams; i++) {
if ((md->streams[i].type == SalVideo) && (md->streams[i].rtp_port != 0))
for (i = 0; i < md->n_active_streams; i++) {
if (md->streams[i].type == SalVideo)
return TRUE;
}
return FALSE;
@ -988,6 +997,7 @@ unsigned int linphone_core_get_audio_features(LinphoneCore *lc){
else if (strcasecmp(name,"VOL_RCV")==0) ret|=AUDIO_STREAM_FEATURE_VOL_RCV;
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,"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);
@ -995,9 +1005,18 @@ unsigned int linphone_core_get_audio_features(LinphoneCore *lc){
p=n;
}
}else ret=AUDIO_STREAM_FEATURE_ALL;
if (ret==AUDIO_STREAM_FEATURE_ALL){
/*since call recording is specified before creation of the stream in linphonecore,
* it will be requested on demand. It is not necessary to include it all the time*/
ret&=~AUDIO_STREAM_FEATURE_MIXED_RECORDING;
}
return ret;
}
bool_t linphone_core_tone_indications_enabled(LinphoneCore*lc){
return lp_config_get_int(lc->config,"sound","tone_indications",1);
}
#ifdef HAVE_GETIFADDRS
@ -1021,14 +1040,15 @@ static int get_local_ip_with_getifaddrs(int type, char *address, int size)
if (ifp->ifa_addr && ifp->ifa_addr->sa_family == type
&& (ifp->ifa_flags & UP_FLAG) && !(ifp->ifa_flags & IFF_LOOPBACK))
{
getnameinfo(ifp->ifa_addr,
if(getnameinfo(ifp->ifa_addr,
(type == AF_INET6) ?
sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in),
address, size, NULL, 0, NI_NUMERICHOST);
if (strchr(address, '%') == NULL) { /*avoid ipv6 link-local addresses */
/*ms_message("getifaddrs() found %s",address);*/
ret++;
break;
address, size, NULL, 0, NI_NUMERICHOST) == 0) {
if (strchr(address, '%') == NULL) { /*avoid ipv6 link-local addresses */
/*ms_message("getifaddrs() found %s",address);*/
ret++;
break;
}
}
}
}
@ -1099,26 +1119,34 @@ static int get_local_ip_for_with_connect(int type, const char *dest, char *resul
}
int linphone_core_get_local_ip_for(int type, const char *dest, char *result){
strcpy(result,type==AF_INET ? "127.0.0.1" : "::1");
#ifdef HAVE_GETIFADDRS
if (dest==NULL) {
/*we use getifaddrs for lookup of default interface */
int found_ifs;
int err;
strcpy(result,type==AF_INET ? "127.0.0.1" : "::1");
found_ifs=get_local_ip_with_getifaddrs(type,result,LINPHONE_IPADDR_SIZE);
if (found_ifs==1){
return 0;
}else if (found_ifs<=0){
/*absolutely no network on this machine */
return -1;
}
if (dest==NULL){
if (type==AF_INET)
dest="87.98.157.38"; /*a public IP address*/
else dest="2a00:1450:8002::68";
}
err=get_local_ip_for_with_connect(type,dest,result);
if (err==0) return 0;
/* if the connect method failed, which happens when no default route is set,
* try to find 'the' running interface with getifaddrs*/
#ifdef HAVE_GETIFADDRS
/*we use getifaddrs for lookup of default interface */
int found_ifs;
found_ifs=get_local_ip_with_getifaddrs(type,result,LINPHONE_IPADDR_SIZE);
if (found_ifs==1){
return 0;
}else if (found_ifs<=0){
/*absolutely no network on this machine */
return -1;
}
#endif
/*else use connect to find the best local ip address */
if (type==AF_INET)
dest="87.98.157.38"; /*a public IP address*/
else dest="2a00:1450:8002::68";
return get_local_ip_for_with_connect(type,dest,result);
return 0;
}
#ifndef WIN32

View file

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

View file

@ -28,9 +28,11 @@
extern "C" {
#endif
#include "linphonecore.h"
#include "linphonefriend.h"
#include "linphone_tunnel.h"
#include "linphonecore_utils.h"
#include "sal.h"
#include "sipsetup.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
@ -38,6 +40,13 @@ extern "C" {
#include "mediastreamer2/ice.h"
#include "mediastreamer2/mediastream.h"
#include "mediastreamer2/msconference.h"
#ifdef BUILD_UPNP
#include "upnp.h"
#endif //BUILD_UPNP
#ifdef MSG_STORAGE_ENABLED
#include "sqlite3.h"
#endif
#ifndef LIBLINPHONE_VERSION
#define LIBLINPHONE_VERSION LINPHONE_VERSION
@ -75,29 +84,60 @@ struct _LinphoneCallParams{
int up_bw;
int down_ptime;
int up_ptime;
char *record_file;
SalCustomHeader *custom_headers;
bool_t has_video;
bool_t real_early_media; /*send real media even during early media (for outgoing calls)*/
bool_t in_conference; /*in conference mode */
bool_t pad;
bool_t low_bandwidth;
};
struct _LinphoneCallLog{
struct _LinphoneCore *lc;
LinphoneCallDir dir; /**< The direction of the call*/
LinphoneCallStatus status; /**< The status of the call*/
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*/
char *refkey;
void *user_pointer;
rtp_stats_t local_stats;
rtp_stats_t remote_stats;
float quality;
time_t start_date_time; /**Start date of the call in seconds as expressed in a time_t */
char* call_id; /**unique id of a call*/
bool_t video_enabled;
};
typedef struct _CallCallbackObj
{
LinphoneCallCbFunc _func;
void * _user_data;
LinphoneCallCbFunc _func;
void * _user_data;
}CallCallbackObj;
static const int linphone_call_magic=0x3343;
typedef enum _LinphoneChatMessageDir{
LinphoneChatMessageIncoming,
LinphoneChatMessageOutgoing
} LinphoneChatMessageDir;
struct _LinphoneChatMessage {
char* message;
LinphoneChatRoom* chat_room;
LinphoneChatMessageDir dir;
char* message;
LinphoneChatMessageStateChangeCb cb;
void* cb_ud;
void* message_userdata;
char* external_body_url;
LinphoneAddress* from;
LinphoneAddress *from;
LinphoneAddress *to;
time_t time;
SalCustomHeader *custom_headers;
LinphoneChatMessageState state;
bool_t is_read;
};
typedef struct StunCandidate{
@ -145,9 +185,14 @@ struct _LinphoneCall
OrtpEvQueue *videostream_app_evq;
CallCallbackObj nextVideoFrameDecoded;
LinphoneCallStats stats[2];
#ifdef BUILD_UPNP
UpnpSession *upnp_session;
#endif //BUILD_UPNP
IceSession *ice_session;
LinphoneChatMessage* pending_message;
int ping_time;
unsigned int remote_session_id;
unsigned int remote_session_ver;
bool_t refer_pending;
bool_t media_pending;
bool_t audio_muted;
@ -165,6 +210,8 @@ struct _LinphoneCall
bool_t was_automatically_paused;
bool_t ping_replied;
bool_t record_active;
bool_t paused_by_app;
};
@ -269,7 +316,7 @@ void linphone_proxy_config_write_to_config_file(struct _LpConfig* config,Linphon
int linphone_proxy_config_normalize_number(LinphoneProxyConfig *cfg, const char *username, char *result, size_t result_len);
void linphone_core_message_received(LinphoneCore *lc, const char *from, const char *raw_msg,const char* external_url);
void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessage *msg);
void linphone_core_play_tone(LinphoneCore *lc);
@ -284,8 +331,10 @@ void linphone_call_stop_audio_stream(LinphoneCall *call);
void linphone_call_stop_video_stream(LinphoneCall *call);
void linphone_call_stop_media_streams(LinphoneCall *call);
void linphone_call_delete_ice_session(LinphoneCall *call);
void linphone_call_delete_upnp_session(LinphoneCall *call);
void linphone_call_stop_media_streams_for_ice_gathering(LinphoneCall *call);
void linphone_call_update_crypto_parameters(LinphoneCall *call, SalMediaDescription *old_md, SalMediaDescription *new_md);
void linphone_call_update_remote_session_id_and_ver(LinphoneCall *call);
const char * linphone_core_get_identity(LinphoneCore *lc);
const char * linphone_core_get_route(LinphoneCore *lc);
@ -357,6 +406,7 @@ struct _LinphoneChatRoom{
char *peer;
LinphoneAddress *peer_url;
void * user_data;
MSList *messages_hist;
};
@ -385,17 +435,18 @@ typedef struct sip_config
MSList *deleted_proxies;
int inc_timeout; /*timeout after an un-answered incoming call is rejected*/
int in_call_timeout; /*timeout after a call is hangup */
int delayed_timeout; /*timeout after a delayed call is resumed */
unsigned int keepalive_period; /* interval in ms between keep alive messages sent to the proxy server*/
LCSipTransports transports;
bool_t use_info;
bool_t use_rfc2833; /*force RFC2833 to be sent*/
bool_t guess_hostname;
bool_t loopback_only;
bool_t ipv6_enabled;
bool_t sdp_200_ack;
bool_t register_only_when_network_is_up;
bool_t register_only_when_upnp_is_ok;
bool_t ping_with_options;
bool_t auto_net_state_mon;
bool_t tcp_tls_keepalive;
} sip_config_t;
typedef struct rtp_config
@ -407,6 +458,7 @@ typedef struct rtp_config
int audio_jitt_comp; /*jitter compensation*/
int video_jitt_comp; /*jitter compensation*/
int nortp_timeout;
int disable_upnp;
bool_t rtp_no_xmit_on_audio_mute;
/* stop rtp xmit when audio muted */
bool_t audio_adaptive_jitt_comp_enabled;
@ -492,6 +544,7 @@ struct _LinphoneConference{
MSAudioConference *conf;
AudioStream *local_participant;
MSAudioEndpoint *local_endpoint;
MSAudioEndpoint *record_endpoint;
RtpProfile *local_dummy_profile;
bool_t local_muted;
};
@ -561,8 +614,8 @@ struct _LinphoneCore
bool_t network_reachable;
bool_t use_preview_window;
time_t network_last_check;
bool_t network_last_status;
time_t network_last_check;
bool_t network_last_status;
bool_t ringstream_autorelease;
bool_t pad[3];
@ -571,13 +624,20 @@ struct _LinphoneCore
LinphoneTunnel *tunnel;
char* device_id;
MSList *last_recv_msg_ids;
char *chat_db_file;
#ifdef MSG_STORAGE_ENABLED
sqlite3 *db;
#endif
#ifdef BUILD_UPNP
UpnpContext *upnp;
#endif //BUILD_UPNP
};
LinphoneTunnel *linphone_core_tunnel_new(LinphoneCore *lc);
void linphone_tunnel_destroy(LinphoneTunnel *tunnel);
void linphone_tunnel_configure(LinphoneTunnel *tunnel);
void linphone_tunnel_enable_logs_with_handler(LinphoneTunnel *tunnel, bool_t enabled, OrtpLogFunc logHandler);
bool_t linphone_core_can_we_add_call(LinphoneCore *lc);
int linphone_core_add_call( LinphoneCore *lc, LinphoneCall *call);
int linphone_core_del_call( LinphoneCore *lc, LinphoneCall *call);
@ -602,12 +662,13 @@ struct _EcCalibrator{
MSTicker *ticker;
LinphoneEcCalibrationCallback cb;
void *cb_data;
int recv_count;
int sent_count;
LinphoneEcCalibrationAudioInit audio_init_cb;
LinphoneEcCalibrationAudioUninit audio_uninit_cb;
int64_t acc;
int delay;
unsigned int rate;
LinphoneEcCalibratorStatus status;
bool_t freq1,freq2,freq3;
};
typedef struct _EcCalibrator EcCalibrator;
@ -618,6 +679,8 @@ void ec_calibrator_destroy(EcCalibrator *ecc);
void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapsed);
void linphone_core_preempt_sound_resources(LinphoneCore *lc);
int _linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call);
/*conferencing subsystem*/
void _post_configure_audio_stream(AudioStream *st, LinphoneCore *lc, bool_t muted);
/* When a conference participant pause the conference he may send a music.
@ -644,6 +707,28 @@ void call_logs_write_to_config_file(LinphoneCore *lc);
int linphone_core_get_edge_bw(LinphoneCore *lc);
int linphone_core_get_edge_ptime(LinphoneCore *lc);
void _linphone_call_params_copy(LinphoneCallParams *params, const LinphoneCallParams *refparams);
void linphone_call_params_uninit(LinphoneCallParams *params);
int linphone_upnp_init(LinphoneCore *lc);
void linphone_upnp_destroy(LinphoneCore *lc);
#ifdef MSG_STORAGE_ENABLED
sqlite3 * linphone_message_storage_init();
#endif
void linphone_chat_message_store(LinphoneChatMessage *msg);
void linphone_chat_message_store_state(LinphoneChatMessage *msg);
void linphone_core_message_storage_init(LinphoneCore *lc);
void linphone_core_message_storage_close(LinphoneCore *lc);
typedef enum _LinphoneToneID{
LinphoneToneBusy,
LinphoneToneCallWaiting,
LinphoneToneCallOnHold,
LinphoneToneCallFailed
}LinphoneToneID;
void linphone_core_play_named_tone(LinphoneCore *lc, LinphoneToneID id);
bool_t linphone_core_tone_indications_enabled(LinphoneCore*lc);
#ifdef __cplusplus
}

View file

@ -263,15 +263,30 @@ static char *guess_contact_for_register(LinphoneProxyConfig *obj){
if (proxy==NULL) return NULL;
host=linphone_address_get_domain (proxy);
if (host!=NULL){
char localip[LINPHONE_IPADDR_SIZE];
int localport = -1;
char localip_tmp[LINPHONE_IPADDR_SIZE] = {'\0'};
const char *localip = NULL;
char *tmp;
LCSipTransports tr;
LinphoneAddress *contact;
linphone_core_get_local_ip(obj->lc,host,localip);
contact=linphone_address_new(obj->reg_identity);
linphone_address_set_domain (contact,localip);
linphone_address_set_port_int(contact,linphone_core_get_sip_port(obj->lc));
#ifdef BUILD_UPNP
if (obj->lc->upnp != NULL && linphone_core_get_firewall_policy(obj->lc)==LinphonePolicyUseUpnp &&
linphone_upnp_context_get_state(obj->lc->upnp) == LinphoneUpnpStateOk) {
localip = linphone_upnp_context_get_external_ipaddress(obj->lc->upnp);
localport = linphone_upnp_context_get_external_port(obj->lc->upnp);
}
#endif //BUILD_UPNP
if(localip == NULL) {
localip = localip_tmp;
linphone_core_get_local_ip(obj->lc,host,localip_tmp);
}
if(localport == -1) {
localport = linphone_core_get_sip_port(obj->lc);
}
linphone_address_set_port_int(contact,localport);
linphone_address_set_domain(contact,localip);
linphone_address_set_display_name(contact,NULL);
linphone_core_get_sip_transports(obj->lc,&tr);
@ -398,7 +413,7 @@ static dial_plan_t const dial_plans[]={
{"Bahrain" ,"BH" , "973" , 8 , "00" },
{"Bangladesh" ,"BD" , "880" , 10 , "00" },
{"Barbados" ,"BB" , "1" , 10 , "011" },
{"Belarus" ,"BY" , "375" , 9 , "00" },
{"Belarus" ,"BY" , "375" , 9 , "00" },
{"Belgium" ,"BE" , "32" , 9 , "00" },
{"Belize" ,"BZ" , "501" , 7 , "00" },
{"Benin" ,"BJ" , "229" , 8 , "00" },
@ -407,12 +422,12 @@ static dial_plan_t const dial_plans[]={
{"Bolivia" ,"BO" , "591" , 8 , "00" },
{"Bosnia and Herzegovina" ,"BA" , "387" , 8 , "00" },
{"Botswana" ,"BW" , "267" , 8 , "00" },
{"Brazil" ,"BR" , "55" , 10 , "00" },
{"Brazil" ,"BR" , "55" , 10 , "00" },
{"Brunei Darussalam" ,"BN" , "673" , 7 , "00" },
{"Bulgaria" ,"BG" , "359" , 9 , "00" },
{"Burkina Faso" ,"BF" , "226" , 8 , "00" },
{"Burundi" ,"BI" , "257" , 8 , "011" },
{"Cambodia" ,"KH" , "855" , 9 , "00" },
{"Cambodia" ,"KH" , "855" , 9 , "00" },
{"Cameroon" ,"CM" , "237" , 8 , "00" },
{"Canada" ,"CA" , "1" , 10 , "011" },
{"Cape Verde" ,"CV" , "238" , 7 , "00" },
@ -421,188 +436,188 @@ static dial_plan_t const dial_plans[]={
{"Chad" ,"TD" , "235" , 8 , "00" },
{"Chile" ,"CL" , "56" , 9 , "00" },
{"China" ,"CN" , "86" , 11 , "00" },
{"Colombia" ,"CO" , "57" , 10 , "00" },
{"Comoros" ,"KM" , "269" , 7 , "00" },
{"Congo" ,"CG" , "242" , 9 , "00" },
{"Congo Democratic Republic" ,"CD" , "243" , 9 , "00" },
{"Cook Islands" ,"CK" , "682" , 5 , "00" },
{"Costa Rica" ,"CR" , "506" , 8 , "00" },
{"C™te d'Ivoire" ,"AD" , "225" , 8 , "00" },
{"Croatia" ,"HR" , "385" , 9 , "00" },
{"Cuba" ,"CU" , "53" , 8 , "119" },
{"Cyprus" ,"CY" , "357" , 8 , "00" },
{"Czech Republic" ,"CZ" , "420" , 9 , "00" },
{"Denmark" ,"DK" , "45" , 8 , "00" },
{"Djibouti" ,"DJ" , "253" , 8 , "00" },
{"Dominica" ,"DM" , "1" , 10 , "011" },
{"Dominican Republic" ,"DO" , "1" , 10 , "011" },
{"Ecuador" ,"EC" , "593" , 9 , "00" },
{"Egypt" ,"EG" , "20" , 10 , "00" },
{"El Salvador" ,"SV" , "503" , 8 , "00" },
{"Equatorial Guinea" ,"GQ" , "240" , 9 , "00" },
{"Eritrea" ,"ER" , "291" , 7 , "00" },
{"Estonia" ,"EE" , "372" , 8 , "00" },
{"Ethiopia" ,"ET" , "251" , 9 , "00" },
{"Falkland Islands" ,"FK" , "500" , 5 , "00" },
{"Faroe Islands" ,"FO" , "298" , 6 , "00" },
{"Fiji" ,"FJ" , "679" , 7 , "00" },
{"Finland" ,"FI" , "358" , 9 , "00" },
{"France" ,"FR" , "33" , 9 , "00" },
{"French Guiana" ,"GF" , "594" , 9 , "00" },
{"French Polynesia" ,"PF" , "689" , 6 , "00" },
{"Gabon" ,"GA" , "241" , 8 , "00" },
{"Gambia" ,"GM" , "220" , 7 , "00" },
{"Georgia" ,"GE" , "995" , 9 , "00" },
{"Germany" ,"DE" , "49" , 11 , "00" },
{"Ghana" ,"GH" , "233" , 9 , "00" },
{"Gibraltar" ,"GI" , "350" , 8 , "00" },
{"Greece" ,"GR" , "30" ,10 , "00" },
{"Greenland" ,"GL" , "299" , 6 , "00" },
{"Grenada" ,"GD" , "1" , 10 , "011" },
{"Guadeloupe" ,"GP" , "590" , 9 , "00" },
{"Guam" ,"GU" , "1" , 10 , "011" },
{"Guatemala" ,"GT" , "502" , 8 , "00" },
{"Guinea" ,"GN" , "224" , 8 , "00" },
{"Guinea-Bissau" ,"GW" , "245" , 7 , "00" },
{"Guyana" ,"GY" , "592" , 7 , "001" },
{"Haiti" ,"HT" , "509" , 8 , "00" },
{"Honduras" ,"HN" , "504" , 8 , "00" },
{"Hong Kong" ,"HK" , "852" , 8 , "001" },
{"Hungary" ,"HU" , "36" , 9 , "00" },
{"Iceland" ,"IS" , "354" , 9 , "00" },
{"India" ,"IN" , "91" , 10 , "00" },
{"Indonesia" ,"ID" , "62" , 10 , "001" },
{"Iran" ,"IR" , "98" , 10 , "00" },
{"Iraq" ,"IQ" , "964" , 10 , "00" },
{"Ireland" ,"IE" , "353" , 9 , "00" },
{"Israel" ,"IL" , "972" , 9 , "00" },
{"Italy" ,"IT" , "39" , 10 , "00" },
{"Jamaica" ,"JM" , "1" , 10 , "011" },
{"Japan" ,"JP" , "81" , 10 , "010" },
{"Jordan" ,"JO" , "962" , 9 , "00" },
{"Kazakhstan" ,"KZ" , "7" , 10 , "00" },
{"Kenya" ,"KE" , "254" , 9 , "000" },
{"Kiribati" ,"KI" , "686" , 5 , "00" },
{"Korea, North" ,"KP" , "850" , 12 , "99" },
{"Korea, South" ,"KR" , "82" , 12 , "001" },
{"Kuwait" ,"KW" , "965" , 8 , "00" },
{"Kyrgyzstan" ,"KG" , "996" , 9 , "00" },
{"Laos" ,"LA" , "856" , 10 , "00" },
{"Latvia" ,"LV" , "371" , 8 , "00" },
{"Lebanon" ,"LB" , "961" , 7 , "00" },
{"Lesotho" ,"LS" , "266" , 8 , "00" },
{"Liberia" ,"LR" , "231" , 8 , "00" },
{"Libya" ,"LY" , "218" , 8 , "00" },
{"Liechtenstein" ,"LI" , "423" , 7 , "00" },
{"Lithuania" ,"LT" , "370" , 8 , "00" },
{"Luxembourg" ,"LU" , "352" , 9 , "00" },
{"Macau" ,"MO" , "853" , 8 , "00" },
{"Macedonia" ,"MK" , "389" , 8 , "00" },
{"Madagascar" ,"MG" , "261" , 9 , "00" },
{"Malawi" ,"MW" , "265" , 9 , "00" },
{"Malaysia" ,"MY" , "60" , 9 , "00" },
{"Maldives" ,"MV" , "960" , 7 , "00" },
{"Mali" ,"ML" , "223" , 8 , "00" },
{"Malta" ,"MT" , "356" , 8 , "00" },
{"Marshall Islands" ,"MH" , "692" , 7 , "011" },
{"Martinique" ,"MQ" , "596" , 9 , "00" },
{"Mauritania" ,"MR" , "222" , 8 , "00" },
{"Mauritius" ,"MU" , "230" , 7 , "00" },
{"Mayotte Island" ,"YT" , "262" , 9 , "00" },
{"Mexico" ,"MX" , "52" , 10 , "00" },
{"Micronesia" ,"FM" , "691" , 7 , "011" },
{"Moldova" ,"MD" , "373" , 8 , "00" },
{"Monaco" ,"MC" , "377" , 8 , "00" },
{"Mongolia" ,"MN" , "976" , 8 , "001" },
{"Montenegro" ,"ME" , "382" , 8 , "00" },
{"Montserrat" ,"MS" , "664" , 10 , "011" },
{"Morocco" ,"MA" , "212" , 9 , "00" },
{"Mozambique" ,"MZ" , "258" , 9 , "00" },
{"Myanmar" ,"MM" , "95" , 8 , "00" },
{"Namibia" ,"NA" , "264" , 9 , "00" },
{"Nauru" ,"NR" , "674" , 7 , "00" },
{"Nepal" ,"NP" , "43" , 10 , "00" },
{"Netherlands" ,"NL" , "31" , 9 , "00" },
{"New Caledonia" ,"NC" , "687" , 6 , "00" },
{"New Zealand" ,"NZ" , "64" , 10 , "00" },
{"Nicaragua" ,"NI" , "505" , 8 , "00" },
{"Niger" ,"NE" , "227" , 8 , "00" },
{"Nigeria" ,"NG" , "234" , 10 , "009" },
{"Niue" ,"NU" , "683" , 4 , "00" },
{"Norfolk Island" ,"NF" , "672" , 5 , "00" },
{"Northern Mariana Islands" ,"MP" , "1" , 10 , "011" },
{"Norway" ,"NO" , "47" , 8 , "00" },
{"Oman" ,"OM" , "968" , 8 , "00" },
{"Pakistan" ,"PK" , "92" , 10 , "00" },
{"Palau" ,"PW" , "680" , 7 , "011" },
{"Palestine" ,"PS" , "970" , 9 , "00" },
{"Panama" ,"PA" , "507" , 8 , "00" },
{"Papua New Guinea" ,"PG" , "675" , 8 , "00" },
{"Paraguay" ,"PY" , "595" , 9 , "00" },
{"Peru" ,"PE" , "51" , 9 , "00" },
{"Philippines" ,"PH" , "63" , 10 , "00" },
{"Poland" ,"PL" , "48" , 9 , "00" },
{"Portugal" ,"PT" , "351" , 9 , "00" },
{"Puerto Rico" ,"PR" , "1" , 10 , "011" },
{"Qatar" ,"QA" , "974" , 8 , "00" },
{"union Island" ,"RE" , "262" , 9 , "011" },
{"Romania" ,"RO" , "40" , 9 , "00" },
{"Russian Federation" ,"RU" , "7" , 10 , "8" },
{"Rwanda" ,"RW" , "250" , 9 , "00" },
{"Saint Helena" ,"SH" , "290" , 4 , "00" },
{"Saint Kitts and Nevis" ,"KN" , "1" , 10 , "011" },
{"Saint Lucia" ,"LC" , "1" , 10 , "011" },
{"Saint Pierre and Miquelon" ,"PM" , "508" , 6 , "00" },
{"Saint Vincent and the Grenadines","VC" , "1" , 10 , "011" },
{"Samoa" ,"WS" , "685" , 7 , "0" },
{"San Marino" ,"SM" , "378" , 10 , "00" },
{"So TomŽ and Prncipe" ,"ST" , "239" , 7 , "00" },
{"Saudi Arabia" ,"SA" , "966" , 9 , "00" },
{"Senegal" ,"SN" , "221" , 9 , "00" },
{"Serbia" ,"RS" , "381" , 9 , "00" },
{"Seychelles" ,"SC" , "248" , 7 , "00" },
{"Sierra Leone" ,"SL" , "232" , 8 , "00" },
{"Singapore" ,"SG" , "65" , 8 , "001" },
{"Slovakia" ,"SK" , "421" , 9 , "00" },
{"Slovenia" ,"SI" , "386" , 8 , "00" },
{"Solomon Islands" ,"SB" , "677" , 7 , "00" },
{"Somalia" ,"SO" , "252" , 8 , "00" },
{"South Africa" ,"ZA" , "27" , 9 , "00" },
{"Spain" ,"ES" , "34" , 9 , "00" },
{"Sri Lanka" ,"LK" , "94" , 9 , "00" },
{"Sudan" ,"SD" , "249" , 9 , "00" },
{"Suriname" ,"SR" , "597" , 7 , "00" },
{"Swaziland" ,"SZ" , "268" , 8 , "00" },
{"Sweden" ,"SE" , "1" , 9 , "00" },
{"Switzerland" ,"XK" , "41" , 9 , "00" },
{"Syria" ,"SY" , "963" , 9 , "00" },
{"Taiwan" ,"TW" , "886" , 9 , "810" },
{"Tajikistan" ,"TJ" , "992" , 9 , "002" },
{"Tanzania" ,"TZ" , "255" , 9 , "000" },
{"Thailand" ,"TH" , "66" , 9 , "001" },
{"Togo" ,"TG" , "228" , 8 , "00" },
{"Tokelau" ,"TK" , "690" , 4 , "00" },
{"Tonga" ,"TO" , "676" , 5 , "00" },
{"Trinidad and Tobago" ,"TT" , "1" , 10 , "011" },
{"Tunisia" ,"TN" , "216" , 8 , "00" },
{"Turkey" ,"TR" , "90" , 10 , "00" },
{"Turkmenistan" ,"TM" , "993" , 8 , "00" },
{"Turks and Caicos Islands" ,"TC" , "1" , 7 , "0" },
{"Tuvalu" ,"TV" , "688" , 5 , "00" },
{"Uganda" ,"UG" , "256" , 9 , "000" },
{"Ukraine" ,"UA" , "380" , 9 , "00" },
{"United Arab Emirates" ,"AE" , "971" , 9 , "00" },
{"United Kingdom" ,"UK" , "44" , 10 , "00" },
{"United States" ,"US" , "1" , 10 , "011" },
{"Uruguay" ,"UY" , "598" , 8 , "00" },
{"Uzbekistan" ,"UZ" , "998" , 9 , "8" },
{"Vanuatu" ,"VU" , "678" , 7 , "00" },
{"Venezuela" ,"VE" , "58" , 10 , "00" },
{"Vietnam" ,"VN" , "84" , 9 , "00" },
{"Wallis and Futuna" ,"WF" , "681" , 5 , "00" },
{"Yemen" ,"YE" , "967" , 9 , "00" },
{"Zambia" ,"ZM" , "260" , 9 , "00" },
{"Zimbabwe" ,"ZW" , "263" , 9 , "00" },
{"Colombia" ,"CO" , "57" , 10 , "00" },
{"Comoros" ,"KM" , "269" , 7 , "00" },
{"Congo" ,"CG" , "242" , 9 , "00" },
{"Congo Democratic Republic" ,"CD" , "243" , 9 , "00" },
{"Cook Islands" ,"CK" , "682" , 5 , "00" },
{"Costa Rica" ,"CR" , "506" , 8 , "00" },
{"C<EFBFBD>te d'Ivoire" ,"AD" , "225" , 8 , "00" },
{"Croatia" ,"HR" , "385" , 9 , "00" },
{"Cuba" ,"CU" , "53" , 8 , "119" },
{"Cyprus" ,"CY" , "357" , 8 , "00" },
{"Czech Republic" ,"CZ" , "420" , 9 , "00" },
{"Denmark" ,"DK" , "45" , 8 , "00" },
{"Djibouti" ,"DJ" , "253" , 8 , "00" },
{"Dominica" ,"DM" , "1" , 10 , "011" },
{"Dominican Republic" ,"DO" , "1" , 10 , "011" },
{"Ecuador" ,"EC" , "593" , 9 , "00" },
{"Egypt" ,"EG" , "20" , 10 , "00" },
{"El Salvador" ,"SV" , "503" , 8 , "00" },
{"Equatorial Guinea" ,"GQ" , "240" , 9 , "00" },
{"Eritrea" ,"ER" , "291" , 7 , "00" },
{"Estonia" ,"EE" , "372" , 8 , "00" },
{"Ethiopia" ,"ET" , "251" , 9 , "00" },
{"Falkland Islands" ,"FK" , "500" , 5 , "00" },
{"Faroe Islands" ,"FO" , "298" , 6 , "00" },
{"Fiji" ,"FJ" , "679" , 7 , "00" },
{"Finland" ,"FI" , "358" , 9 , "00" },
{"France" ,"FR" , "33" , 9 , "00" },
{"French Guiana" ,"GF" , "594" , 9 , "00" },
{"French Polynesia" ,"PF" , "689" , 6 , "00" },
{"Gabon" ,"GA" , "241" , 8 , "00" },
{"Gambia" ,"GM" , "220" , 7 , "00" },
{"Georgia" ,"GE" , "995" , 9 , "00" },
{"Germany" ,"DE" , "49" , 11 , "00" },
{"Ghana" ,"GH" , "233" , 9 , "00" },
{"Gibraltar" ,"GI" , "350" , 8 , "00" },
{"Greece" ,"GR" , "30" ,10 , "00" },
{"Greenland" ,"GL" , "299" , 6 , "00" },
{"Grenada" ,"GD" , "1" , 10 , "011" },
{"Guadeloupe" ,"GP" , "590" , 9 , "00" },
{"Guam" ,"GU" , "1" , 10 , "011" },
{"Guatemala" ,"GT" , "502" , 8 , "00" },
{"Guinea" ,"GN" , "224" , 8 , "00" },
{"Guinea-Bissau" ,"GW" , "245" , 7 , "00" },
{"Guyana" ,"GY" , "592" , 7 , "001" },
{"Haiti" ,"HT" , "509" , 8 , "00" },
{"Honduras" ,"HN" , "504" , 8 , "00" },
{"Hong Kong" ,"HK" , "852" , 8 , "001" },
{"Hungary" ,"HU" , "36" , 9 , "00" },
{"Iceland" ,"IS" , "354" , 9 , "00" },
{"India" ,"IN" , "91" , 10 , "00" },
{"Indonesia" ,"ID" , "62" , 10 , "001" },
{"Iran" ,"IR" , "98" , 10 , "00" },
{"Iraq" ,"IQ" , "964" , 10 , "00" },
{"Ireland" ,"IE" , "353" , 9 , "00" },
{"Israel" ,"IL" , "972" , 9 , "00" },
{"Italy" ,"IT" , "39" , 10 , "00" },
{"Jamaica" ,"JM" , "1" , 10 , "011" },
{"Japan" ,"JP" , "81" , 10 , "010" },
{"Jordan" ,"JO" , "962" , 9 , "00" },
{"Kazakhstan" ,"KZ" , "7" , 10 , "00" },
{"Kenya" ,"KE" , "254" , 9 , "000" },
{"Kiribati" ,"KI" , "686" , 5 , "00" },
{"Korea, North" ,"KP" , "850" , 12 , "99" },
{"Korea, South" ,"KR" , "82" , 12 , "001" },
{"Kuwait" ,"KW" , "965" , 8 , "00" },
{"Kyrgyzstan" ,"KG" , "996" , 9 , "00" },
{"Laos" ,"LA" , "856" , 10 , "00" },
{"Latvia" ,"LV" , "371" , 8 , "00" },
{"Lebanon" ,"LB" , "961" , 7 , "00" },
{"Lesotho" ,"LS" , "266" , 8 , "00" },
{"Liberia" ,"LR" , "231" , 8 , "00" },
{"Libya" ,"LY" , "218" , 8 , "00" },
{"Liechtenstein" ,"LI" , "423" , 7 , "00" },
{"Lithuania" ,"LT" , "370" , 8 , "00" },
{"Luxembourg" ,"LU" , "352" , 9 , "00" },
{"Macau" ,"MO" , "853" , 8 , "00" },
{"Macedonia" ,"MK" , "389" , 8 , "00" },
{"Madagascar" ,"MG" , "261" , 9 , "00" },
{"Malawi" ,"MW" , "265" , 9 , "00" },
{"Malaysia" ,"MY" , "60" , 9 , "00" },
{"Maldives" ,"MV" , "960" , 7 , "00" },
{"Mali" ,"ML" , "223" , 8 , "00" },
{"Malta" ,"MT" , "356" , 8 , "00" },
{"Marshall Islands" ,"MH" , "692" , 7 , "011" },
{"Martinique" ,"MQ" , "596" , 9 , "00" },
{"Mauritania" ,"MR" , "222" , 8 , "00" },
{"Mauritius" ,"MU" , "230" , 7 , "00" },
{"Mayotte Island" ,"YT" , "262" , 9 , "00" },
{"Mexico" ,"MX" , "52" , 10 , "00" },
{"Micronesia" ,"FM" , "691" , 7 , "011" },
{"Moldova" ,"MD" , "373" , 8 , "00" },
{"Monaco" ,"MC" , "377" , 8 , "00" },
{"Mongolia" ,"MN" , "976" , 8 , "001" },
{"Montenegro" ,"ME" , "382" , 8 , "00" },
{"Montserrat" ,"MS" , "664" , 10 , "011" },
{"Morocco" ,"MA" , "212" , 9 , "00" },
{"Mozambique" ,"MZ" , "258" , 9 , "00" },
{"Myanmar" ,"MM" , "95" , 8 , "00" },
{"Namibia" ,"NA" , "264" , 9 , "00" },
{"Nauru" ,"NR" , "674" , 7 , "00" },
{"Nepal" ,"NP" , "43" , 10 , "00" },
{"Netherlands" ,"NL" , "31" , 9 , "00" },
{"New Caledonia" ,"NC" , "687" , 6 , "00" },
{"New Zealand" ,"NZ" , "64" , 10 , "00" },
{"Nicaragua" ,"NI" , "505" , 8 , "00" },
{"Niger" ,"NE" , "227" , 8 , "00" },
{"Nigeria" ,"NG" , "234" , 10 , "009" },
{"Niue" ,"NU" , "683" , 4 , "00" },
{"Norfolk Island" ,"NF" , "672" , 5 , "00" },
{"Northern Mariana Islands" ,"MP" , "1" , 10 , "011" },
{"Norway" ,"NO" , "47" , 8 , "00" },
{"Oman" ,"OM" , "968" , 8 , "00" },
{"Pakistan" ,"PK" , "92" , 10 , "00" },
{"Palau" ,"PW" , "680" , 7 , "011" },
{"Palestine" ,"PS" , "970" , 9 , "00" },
{"Panama" ,"PA" , "507" , 8 , "00" },
{"Papua New Guinea" ,"PG" , "675" , 8 , "00" },
{"Paraguay" ,"PY" , "595" , 9 , "00" },
{"Peru" ,"PE" , "51" , 9 , "00" },
{"Philippines" ,"PH" , "63" , 10 , "00" },
{"Poland" ,"PL" , "48" , 9 , "00" },
{"Portugal" ,"PT" , "351" , 9 , "00" },
{"Puerto Rico" ,"PR" , "1" , 10 , "011" },
{"Qatar" ,"QA" , "974" , 8 , "00" },
{"R<EFBFBD>union Island" ,"RE" , "262" , 9 , "011" },
{"Romania" ,"RO" , "40" , 9 , "00" },
{"Russian Federation" ,"RU" , "7" , 10 , "8" },
{"Rwanda" ,"RW" , "250" , 9 , "00" },
{"Saint Helena" ,"SH" , "290" , 4 , "00" },
{"Saint Kitts and Nevis" ,"KN" , "1" , 10 , "011" },
{"Saint Lucia" ,"LC" , "1" , 10 , "011" },
{"Saint Pierre and Miquelon" ,"PM" , "508" , 6 , "00" },
{"Saint Vincent and the Grenadines","VC" , "1" , 10 , "011" },
{"Samoa" ,"WS" , "685" , 7 , "0" },
{"San Marino" ,"SM" , "378" , 10 , "00" },
{"S<EFBFBD>o Tom<6F> and Pr<50>ncipe" ,"ST" , "239" , 7 , "00" },
{"Saudi Arabia" ,"SA" , "966" , 9 , "00" },
{"Senegal" ,"SN" , "221" , 9 , "00" },
{"Serbia" ,"RS" , "381" , 9 , "00" },
{"Seychelles" ,"SC" , "248" , 7 , "00" },
{"Sierra Leone" ,"SL" , "232" , 8 , "00" },
{"Singapore" ,"SG" , "65" , 8 , "001" },
{"Slovakia" ,"SK" , "421" , 9 , "00" },
{"Slovenia" ,"SI" , "386" , 8 , "00" },
{"Solomon Islands" ,"SB" , "677" , 7 , "00" },
{"Somalia" ,"SO" , "252" , 8 , "00" },
{"South Africa" ,"ZA" , "27" , 9 , "00" },
{"Spain" ,"ES" , "34" , 9 , "00" },
{"Sri Lanka" ,"LK" , "94" , 9 , "00" },
{"Sudan" ,"SD" , "249" , 9 , "00" },
{"Suriname" ,"SR" , "597" , 7 , "00" },
{"Swaziland" ,"SZ" , "268" , 8 , "00" },
{"Sweden" ,"SE" , "1" , 9 , "00" },
{"Switzerland" ,"XK" , "41" , 9 , "00" },
{"Syria" ,"SY" , "963" , 9 , "00" },
{"Taiwan" ,"TW" , "886" , 9 , "810" },
{"Tajikistan" ,"TJ" , "992" , 9 , "002" },
{"Tanzania" ,"TZ" , "255" , 9 , "000" },
{"Thailand" ,"TH" , "66" , 9 , "001" },
{"Togo" ,"TG" , "228" , 8 , "00" },
{"Tokelau" ,"TK" , "690" , 4 , "00" },
{"Tonga" ,"TO" , "676" , 5 , "00" },
{"Trinidad and Tobago" ,"TT" , "1" , 10 , "011" },
{"Tunisia" ,"TN" , "216" , 8 , "00" },
{"Turkey" ,"TR" , "90" , 10 , "00" },
{"Turkmenistan" ,"TM" , "993" , 8 , "00" },
{"Turks and Caicos Islands" ,"TC" , "1" , 7 , "0" },
{"Tuvalu" ,"TV" , "688" , 5 , "00" },
{"Uganda" ,"UG" , "256" , 9 , "000" },
{"Ukraine" ,"UA" , "380" , 9 , "00" },
{"United Arab Emirates" ,"AE" , "971" , 9 , "00" },
{"United Kingdom" ,"UK" , "44" , 10 , "00" },
{"United States" ,"US" , "1" , 10 , "011" },
{"Uruguay" ,"UY" , "598" , 8 , "00" },
{"Uzbekistan" ,"UZ" , "998" , 9 , "8" },
{"Vanuatu" ,"VU" , "678" , 7 , "00" },
{"Venezuela" ,"VE" , "58" , 10 , "00" },
{"Vietnam" ,"VN" , "84" , 9 , "00" },
{"Wallis and Futuna" ,"WF" , "681" , 5 , "00" },
{"Yemen" ,"YE" , "967" , 9 , "00" },
{"Zambia" ,"ZM" , "260" , 9 , "00" },
{"Zimbabwe" ,"ZW" , "263" , 9 , "00" },
{NULL ,NULL , "" , 0 , NULL }
};
static dial_plan_t most_common_dialplan={ "generic" ,"", "", 10, "00"};
@ -777,6 +792,7 @@ int linphone_proxy_config_send_publish(LinphoneProxyConfig *proxy,
LinphoneOnlineStatus presence_mode){
int err;
SalOp *op=sal_op_new(proxy->lc->sal);
sal_op_set_route(op,proxy->reg_proxy);
err=sal_publish(op,linphone_proxy_config_get_identity(proxy),
linphone_proxy_config_get_identity(proxy),linphone_online_status_to_sal(presence_mode));
if (proxy->publish_op!=NULL)
@ -1076,18 +1092,40 @@ SipSetup *linphone_proxy_config_get_sip_setup(LinphoneProxyConfig *cfg){
return NULL;
}
static bool_t can_register(LinphoneProxyConfig *cfg){
LinphoneCore *lc=cfg->lc;
#ifdef BUILD_UPNP
if (linphone_core_get_firewall_policy(lc)==LinphonePolicyUseUpnp){
if(lc->sip_conf.register_only_when_upnp_is_ok &&
(lc->upnp == NULL || !linphone_upnp_context_is_ready_for_register(lc->upnp))) {
return FALSE;
}
}
#endif //BUILD_UPNP
if (lc->sip_conf.register_only_when_network_is_up){
LinphoneTunnel *tunnel=linphone_core_get_tunnel(lc);
if (tunnel && linphone_tunnel_enabled(tunnel)){
return linphone_tunnel_connected(tunnel);
}else{
return lc->network_reachable;
}
}
return TRUE;
}
void linphone_proxy_config_update(LinphoneProxyConfig *cfg){
LinphoneCore *lc=cfg->lc;
if (cfg->commit){
if (cfg->type && cfg->ssctx==NULL){
linphone_proxy_config_activate_sip_setup(cfg);
}
if (!lc->sip_conf.register_only_when_network_is_up || lc->network_reachable)
if (can_register(cfg)){
linphone_proxy_config_register(cfg);
if (cfg->publish && cfg->publish_op==NULL){
linphone_proxy_config_send_publish(cfg,lc->presence_mode);
if (cfg->publish && cfg->publish_op==NULL){
linphone_proxy_config_send_publish(cfg,lc->presence_mode);
}
cfg->commit=FALSE;
}
cfg->commit=FALSE;
}
}

View file

@ -76,7 +76,7 @@ void sal_media_description_unref(SalMediaDescription *md){
SalStreamDescription *sal_media_description_find_stream(SalMediaDescription *md,
SalMediaProto proto, SalStreamType type){
int i;
for(i=0;i<md->nstreams;++i){
for(i=0;i<md->n_active_streams;++i){
SalStreamDescription *ss=&md->streams[i];
if (ss->proto==proto && ss->type==type) return ss;
}
@ -84,17 +84,13 @@ SalStreamDescription *sal_media_description_find_stream(SalMediaDescription *md,
}
bool_t sal_media_description_empty(const SalMediaDescription *md){
int i;
for(i=0;i<md->nstreams;++i){
const SalStreamDescription *ss=&md->streams[i];
if (ss->rtp_port!=0) return FALSE;
}
if (md->n_active_streams > 0) return FALSE;
return TRUE;
}
void sal_media_description_set_dir(SalMediaDescription *md, SalStreamDir stream_dir){
int i;
for(i=0;i<md->nstreams;++i){
for(i=0;i<md->n_active_streams;++i){
SalStreamDescription *ss=&md->streams[i];
ss->dir=stream_dir;
}
@ -110,7 +106,7 @@ static bool_t has_dir(const SalMediaDescription *md, SalStreamDir stream_dir){
int i;
/* we are looking for at least one stream with requested direction, inactive streams are ignored*/
for(i=0;i<md->nstreams;++i){
for(i=0;i<md->n_active_streams;++i){
const SalStreamDescription *ss=&md->streams[i];
if (ss->dir==stream_dir) return TRUE;
/*compatibility check for phones that only used the null address and no attributes */
@ -224,9 +220,9 @@ int sal_media_description_equals(const SalMediaDescription *md1, const SalMediaD
int i;
if (strcmp(md1->addr, md2->addr) != 0) result |= SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED;
if (md1->nstreams != md2->nstreams) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED;
if (md1->n_total_streams != md2->n_total_streams) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED;
if (md1->bandwidth != md2->bandwidth) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED;
for(i = 0; i < md1->nstreams; ++i){
for(i = 0; i < md1->n_total_streams; ++i){
result |= sal_stream_description_equals(&md1->streams[i], &md2->streams[i]);
}
return result;
@ -277,6 +273,10 @@ const char *sal_op_get_contact(const SalOp *op){
return ((SalOpBase*)op)->contact;
}
const char *sal_op_get_remote_contact(const SalOp *op){
return ((SalOpBase*)op)->remote_contact;
}
const char *sal_op_get_route(const SalOp *op){
return ((SalOpBase*)op)->route;
}
@ -308,6 +308,9 @@ void __sal_op_set_network_origin(SalOp *op, const char *origin){
assign_string(&((SalOpBase*)op)->origin,origin);
}
void __sal_op_set_remote_contact(SalOp *op, const char *ct){
assign_string(&((SalOpBase*)op)->remote_contact,ct);
}
void __sal_op_free(SalOp *op){
SalOpBase *b=(SalOpBase *)op;
@ -335,12 +338,18 @@ void __sal_op_free(SalOp *op){
ms_free(b->remote_ua);
b->remote_ua=NULL;
}
if (b->remote_contact){
ms_free(b->remote_contact);
b->remote_contact=NULL;
}
if (b->local_media)
sal_media_description_unref(b->local_media);
if (b->remote_media)
sal_media_description_unref(b->remote_media);
if (b->call_id)
ms_free((void*)b->call_id);
ms_free(b->call_id);
if (b->custom_headers)
sal_custom_header_free(b->custom_headers);
ms_free(op);
}
@ -365,3 +374,60 @@ void sal_auth_info_delete(const SalAuthInfo* auth_info) {
ms_free((void*)auth_info);
}
SalCustomHeader *sal_custom_header_append(SalCustomHeader *ch, const char *name, const char *value){
SalCustomHeader *h=ms_new0(SalCustomHeader,1);
h->header_name=ms_strdup(name);
h->header_value=ms_strdup(value);
h->node.data=h;
return (SalCustomHeader*)ms_list_append_link((MSList*)ch,(MSList*)h);
}
const char *sal_custom_header_find(const SalCustomHeader *ch, const char *name){
const MSList *it;
for (it=(const MSList*)ch;it!=NULL;it=it->next){
const SalCustomHeader *itch=(const SalCustomHeader *)it;
if (strcasecmp(itch->header_name,name)==0)
return itch->header_value;
}
return NULL;
}
static void sal_custom_header_uninit(SalCustomHeader *ch){
ms_free(ch->header_name);
ms_free(ch->header_value);
}
void sal_custom_header_free(SalCustomHeader *ch){
ms_list_for_each((MSList*)ch,(void (*)(void*))sal_custom_header_uninit);
ms_list_free((MSList *)ch);
}
SalCustomHeader *sal_custom_header_clone(const SalCustomHeader *ch){
const MSList *it;
SalCustomHeader *ret=NULL;
for (it=(const MSList*)ch;it!=NULL;it=it->next){
const SalCustomHeader *itch=(const SalCustomHeader *)it;
ret=sal_custom_header_append(ret,itch->header_name,itch->header_value);
}
return ret;
}
const SalCustomHeader *sal_op_get_custom_header(SalOp *op){
SalOpBase *b=(SalOpBase *)op;
return b->custom_headers;
}
/*
* Warning: this function takes owneship of the custom headers
*/
void sal_op_set_custom_header(SalOp *op, SalCustomHeader* ch){
SalOpBase *b=(SalOpBase *)op;
if (b->custom_headers){
sal_custom_header_free(b->custom_headers);
b->custom_headers=NULL;
}
b->custom_headers=ch;
}

View file

@ -46,6 +46,10 @@ struct SalAddress;
typedef struct SalAddress SalAddress;
struct SalCustomHeader;
typedef struct SalCustomHeader SalCustomHeader;
typedef enum {
SalTransportUDP, /*UDP*/
SalTransportTCP, /*TCP*/
@ -178,7 +182,8 @@ typedef struct SalMediaDescription{
int refcount;
char addr[64];
char username[64];
int nstreams;
int n_active_streams;
int n_total_streams;
int bandwidth;
unsigned int session_ver;
unsigned int session_id;
@ -194,6 +199,7 @@ typedef struct SalMessage{
const char *text;
const char *url;
const char *message_id;
time_t time;
}SalMessage;
#define SAL_MEDIA_DESCRIPTION_MAX_MESSAGE_ATTRIBUTES 5
@ -220,7 +226,9 @@ typedef struct SalOpBase{
SalMediaDescription *local_media;
SalMediaDescription *remote_media;
void *user_pointer;
const char* call_id;
char* call_id;
char *remote_contact;
SalCustomHeader *custom_headers;
} SalOpBase;
@ -288,7 +296,7 @@ typedef void (*SalOnRegisterFailure)(SalOp *op, SalError error, SalReason reason
typedef void (*SalOnVfuRequest)(SalOp *op);
typedef void (*SalOnDtmfReceived)(SalOp *op, char dtmf);
typedef void (*SalOnRefer)(Sal *sal, SalOp *op, const char *referto);
typedef void (*SalOnTextReceived)(Sal *sal, const SalMessage *msg);
typedef void (*SalOnTextReceived)(SalOp *op, const SalMessage *msg);
typedef void (*SalOnTextDeliveryUpdate)(SalOp *op, SalTextDeliveryStatus status);
typedef void (*SalOnNotify)(SalOp *op, const char *from, const char *event);
typedef void (*SalOnNotifyRefer)(SalOp *op, SalReferStatus state);
@ -343,6 +351,7 @@ ortp_socket_t sal_get_socket(Sal *ctx);
void sal_set_user_agent(Sal *ctx, const char *user_agent);
/*keepalive period in ms*/
void sal_set_keepalive_period(Sal *ctx,unsigned int value);
void sal_use_tcp_tls_keepalive(Sal *ctx, bool_t enabled);
/**
* returns keepalive period in ms
* 0 desactiaved
@ -383,6 +392,7 @@ const char *sal_op_get_to(const SalOp *op);
const char *sal_op_get_contact(const SalOp *op);
const char *sal_op_get_route(const SalOp *op);
const char *sal_op_get_proxy(const SalOp *op);
const char *sal_op_get_remote_contact(const SalOp *op);
/*for incoming requests, returns the origin of the packet as a sip uri*/
const char *sal_op_get_network_origin(const SalOp *op);
/*returns far-end "User-Agent" string */
@ -440,16 +450,30 @@ int sal_ping(SalOp *op, const char *from, const char *to);
#define payload_type_set_number(pt,n) (pt)->user_data=(void*)((long)n);
#define payload_type_set_number(pt,n) (pt)->user_data=(void*)((long)n);
#define payload_type_get_number(pt) ((int)(long)(pt)->user_data)
/*misc*/
void sal_get_default_local_ip(Sal *sal, int address_family, char *ip, size_t iplen);
struct SalCustomHeader{
MSList node;
char *header_name;
char *header_value;
};
SalCustomHeader *sal_custom_header_append(SalCustomHeader *ch, const char *name, const char *value);
const char *sal_custom_header_find(const SalCustomHeader *ch, const char *name);
void sal_custom_header_free(SalCustomHeader *ch);
SalCustomHeader *sal_custom_header_clone(const SalCustomHeader *ch);
const SalCustomHeader *sal_op_get_custom_header(SalOp *op);
void sal_op_set_custom_header(SalOp *op, SalCustomHeader* ch);
/*internal API */
void __sal_op_init(SalOp *b, Sal *sal);
void __sal_op_set_network_origin(SalOp *op, const char *origin /*a sip uri*/);
void __sal_op_set_remote_contact(SalOp *op, const char *ct);
void __sal_op_free(SalOp *b);
#endif

File diff suppressed because it is too large Load diff

View file

@ -30,6 +30,7 @@ int sdp_to_media_description(sdp_message_t *sdp, SalMediaDescription *desc);
struct Sal{
SalCallbacks callbacks;
SalTransport transport;
MSList *calls; /*MSList of SalOp */
MSList *registers;/*MSList of SalOp */
MSList *out_subscribes;/*MSList of SalOp */
@ -51,6 +52,7 @@ struct Sal{
bool_t verify_server_cn;
bool_t expire_old_contact;
bool_t add_dates;
bool_t tcp_tls_keepalive;
};
struct SalOp{
@ -92,7 +94,11 @@ void sal_exosip_in_subscription_closed(Sal *sal, eXosip_event_t *ev);
SalOp * sal_find_out_subscribe(Sal *sal, int sid);
SalOp * sal_find_in_subscribe(Sal *sal, int nid);
void sal_exosip_fix_route(SalOp *op);
void sal_exosip_add_custom_headers(osip_message_t *msg, SalCustomHeader *ch);
SalCustomHeader * sal_exosip_get_custom_headers(osip_message_t *msg);
void _osip_list_set_empty(osip_list_t *l, void (*freefunc)(void*));
void sal_message_add_route(osip_message_t *msg, const char *proxy);
#endif

View file

@ -81,6 +81,26 @@ void sal_remove_in_subscribe(Sal *sal, SalOp *op){
sal->in_subscribes=ms_list_remove(sal->in_subscribes,op);
}
static const char *days[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
static const char *months[]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
static void msg_add_current_date(osip_message_t *msg){
char tmp[64]={0};
time_t curtime=time(NULL);
struct tm *ret;
#ifndef WIN32
struct tm gmt;
ret=gmtime_r(&curtime,&gmt);
#else
ret=gmtime(&curtime);
#endif
/*cannot use strftime because it is locale dependant*/
snprintf(tmp,sizeof(tmp)-1,"%s, %i %s %i %02i:%02i:%02i GMT",
days[ret->tm_wday],ret->tm_mday,months[ret->tm_mon],1900+ret->tm_year,ret->tm_hour,ret->tm_min,ret->tm_sec);
osip_message_replace_header(msg,"Date",tmp);
}
int sal_message_send(SalOp *op, const char *from, const char *to, const char* content_type, const char *msg){
osip_message_t *sip=NULL;
@ -97,6 +117,8 @@ int sal_message_send(SalOp *op, const char *from, const char *to, const char* co
eXosip_message_build_request(&sip,"MESSAGE",sal_op_get_to(op),
sal_op_get_from(op),sal_op_get_route(op));
if (sip!=NULL){
sal_exosip_add_custom_headers(sip,op->base.custom_headers);
msg_add_current_date(sip);
osip_message_set_content_type(sip,content_type);
if (msg) osip_message_set_body(sip,msg,strlen(msg));
sal_add_other(op->base.root,op,sip);
@ -118,6 +140,8 @@ int sal_message_send(SalOp *op, const char *from, const char *to, const char* co
eXosip_unlock();
return -1;
}
sal_exosip_add_custom_headers(sip,op->base.custom_headers);
msg_add_current_date(sip);
osip_message_set_content_type(sip,content_type);
if (msg) osip_message_set_body(sip,msg,strlen(msg));
eXosip_call_send_request(op->did,sip);
@ -125,6 +149,7 @@ int sal_message_send(SalOp *op, const char *from, const char *to, const char* co
}
return 0;
}
int sal_text_send(SalOp *op, const char *from, const char *to, const char *msg) {
return sal_message_send(op,from,to,"text/plain",msg);
}
@ -612,23 +637,26 @@ int sal_publish(SalOp *op, const char *from, const char *to, SalPresenceStatus p
osip_message_t *pub;
int i;
char buf[1024];
const char *route=sal_op_get_route(op);
mk_presence_body (presence_mode, from, buf, sizeof (buf), presence_style);
i = eXosip_build_publish(&pub,from, to, NULL, "presence", "300",
i = eXosip_build_publish(&pub,to, from, NULL, "presence", "600",
presence_style ? "application/xpidf+xml" : "application/pidf+xml", buf);
if (i<0){
ms_warning("Failed to build publish request.");
return -1;
}
if (route)
sal_message_add_route(pub,route);
eXosip_lock();
i = eXosip_publish(pub, to); /* should update the sip-if-match parameter
from sip-etag from last 200ok of PUBLISH */
eXosip_unlock();
if (i<0){
ms_message("Failed to send publish request.");
return -1;
ms_message("Failed to send publish request.");
return -1;
}
sal_add_other(sal_op_get_sal(op),op,pub);
return 0;

View file

@ -24,7 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "sal.h"
#include <eXosip2/eXosip.h>
#define keywordcmp(key,b) strncmp(key,b,sizeof(key))
#define keywordcmp(key,b) strcmp(key,b)
#ifdef FOR_LATER
@ -394,7 +394,7 @@ static void add_line(sdp_message_t *msg, int lineno, const SalStreamDescription
sdp_message_t *media_description_to_sdp(const SalMediaDescription *desc){
int i;
sdp_message_t *msg=create_generic_sdp(desc);
for(i=0;i<desc->nstreams;++i){
for(i=0;i<desc->n_total_streams;++i){
add_line(msg,i,&desc->streams[i]);
}
return msg;
@ -434,10 +434,17 @@ static int payload_type_fill_from_rtpmap(PayloadType *pt, const char *rtpmap){
int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc){
int i,j;
const char *mtype,*proto,*rtp_port,*rtp_addr,*number;
const char *sess;
sdp_bandwidth_t *sbw=NULL;
sdp_attribute_t *attr;
int nb_ice_candidates;
/* Get session information. */
sess = sdp_message_o_sess_id_get(msg);
if (sess) desc->session_id = strtoul(sess, NULL, 10);
sess = sdp_message_o_sess_version_get(msg);
if (sess) desc->session_ver = strtoul(sess, NULL, 10);
rtp_addr=sdp_message_c_addr_get (msg, -1, 0);
if (rtp_addr)
strncpy(desc->addr,rtp_addr,sizeof(desc->addr));
@ -456,6 +463,8 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc){
}
}
desc->n_active_streams = 0;
/* for each m= line */
for (i=0; !sdp_message_endof_media (msg, i) && i<SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++)
{
@ -479,6 +488,8 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc){
strncpy(stream->rtp_addr,rtp_addr,sizeof(stream->rtp_addr));
if (rtp_port)
stream->rtp_port=atoi(rtp_port);
if (stream->rtp_port > 0)
desc->n_active_streams++;
stream->ptime=_sdp_message_get_a_ptime(msg,i);
if (strcasecmp("audio", mtype) == 0){
@ -536,7 +547,7 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc){
for (k=0;valid_count < SAL_CRYPTO_ALGO_MAX && (attr=sdp_message_attribute_get(msg,i,k))!=NULL;k++){
char tmp[256], tmp2[256];
if (keywordcmp("crypto",attr->a_att_field)==0 && attr->a_att_value!=NULL){
int nb = sscanf(attr->a_att_value, "%d %256s inline:%256s",
int nb = sscanf(attr->a_att_value, "%d %255s inline:%255s",
&stream->crypto[valid_count].tag,
tmp,
tmp2);
@ -602,6 +613,6 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc){
}
}
}
desc->nstreams=i;
desc->n_total_streams=i;
return 0;
}

View file

@ -45,7 +45,7 @@ int main(int argc, char *argv[]){
linphone_core_enable_logs(NULL);
linphone_core_start_echo_calibration(lc,calibration_finished,NULL);
linphone_core_start_echo_calibration(lc,calibration_finished,NULL,NULL,NULL);
while(count++<1000){
linphone_core_iterate(lc);

1347
coreapi/upnp.c Normal file

File diff suppressed because it is too large Load diff

48
coreapi/upnp.h Normal file
View file

@ -0,0 +1,48 @@
/*
linphone
Copyright (C) 2012 Belledonne Communications SARL
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef LINPHONE_UPNP_H
#define LINPHONE_UPNP_H
#include "mediastreamer2/upnp_igd.h"
#include "linphonecore.h"
#include "sal.h"
typedef struct _UpnpSession UpnpSession;
typedef struct _UpnpContext UpnpContext;
int linphone_core_update_local_media_description_from_upnp(SalMediaDescription *desc, UpnpSession *session);
int linphone_core_update_upnp_from_remote_media_description(LinphoneCall *call, const SalMediaDescription *md);
int linphone_core_update_upnp(LinphoneCore *lc, LinphoneCall *call);
int linphone_upnp_call_process(LinphoneCall *call);
UpnpSession* linphone_upnp_session_new(LinphoneCall *call);
void linphone_upnp_session_destroy(UpnpSession* session);
LinphoneUpnpState linphone_upnp_session_get_state(UpnpSession *session);
UpnpContext *linphone_upnp_context_new(LinphoneCore *lc);
void linphone_upnp_context_destroy(UpnpContext *ctx);
void linphone_upnp_refresh(UpnpContext *ctx);
LinphoneUpnpState linphone_upnp_context_get_state(UpnpContext *ctx);
const char *linphone_upnp_context_get_external_ipaddress(UpnpContext *ctx);
int linphone_upnp_context_get_external_port(UpnpContext *ctx);
bool_t linphone_upnp_context_is_ready_for_register(UpnpContext *ctx);
void linphone_core_update_upnp_state_in_call_stats(LinphoneCall *call);
#endif //LINPHONE_UPNP_H

View file

@ -27,6 +27,9 @@ FirewallPolicyResponse::FirewallPolicyResponse(LinphoneCore *core) : Response()
ost << "ice\n";
ost << "Address: " << linphone_core_get_stun_server(core) << "\n";
break;
case LinphonePolicyUseUpnp:
ost << "upnp\n";
break;
}
setBody(ost.str().c_str());
}
@ -34,7 +37,7 @@ FirewallPolicyResponse::FirewallPolicyResponse(LinphoneCore *core) : Response()
FirewallPolicyCommand::FirewallPolicyCommand() :
DaemonCommand("firewall-policy", "firewall-policy <type> [<address>]",
"Set the firewall policy if type is set, otherwise return the used firewall policy.\n"
"<type> must be one of these values: none, nat, stun, ice.\n"
"<type> must be one of these values: none, nat, stun, ice, upnp.\n"
"<address> must be specified for the 'nat' and 'stun' types. "
"It represents the public address of the gateway for the 'nat' type and the STUN server address for the 'stun' and 'ice' types.") {
addExample(new DaemonCommandExample("firewall-policy stun stun.linphone.org",
@ -73,6 +76,9 @@ void FirewallPolicyCommand::exec(Daemon *app, const char *args) {
} else if (type.compare("ice") == 0) {
policy = LinphonePolicyUseIce;
get_address = true;
} else if (type.compare("upnp") == 0) {
policy = LinphonePolicyUseUpnp;
get_address = false;
} else {
app->sendResponse(Response("Incorrect type parameter.", Response::Error));
return;

View file

@ -5,6 +5,7 @@ UI_FILES= about.ui \
parameters.ui \
sip_account.ui \
call_logs.ui \
keypad.ui \
log.ui \
buddylookup.ui \
tunnel_config.ui \
@ -53,10 +54,8 @@ linphone_SOURCES+= \
setupwizard.c
endif
linphone_LDADD=$(ORTP_LIBS) \
$(MEDIASTREAMER_LIBS) \
$(top_builddir)/coreapi/liblinphone.la \
$(LIBGTK_LIBS) $(NOTIFY1_LIBS) $(NOTIFY4_LIBS) $(LIBGTKMAC_LIBS) $(INTLLIBS)
linphone_LDADD= $(top_builddir)/coreapi/liblinphone.la \
$(LIBGTK_LIBS) $(NOTIFY1_LIBS) $(NOTIFY4_LIBS) $(LIBGTKMAC_LIBS) $(INTLLIBS) $(SQLITE3_LIBS)
if BUILD_WIN32
@ -80,7 +79,8 @@ AM_CFLAGS= -DIN_LINPHONE -I$(top_srcdir)/coreapi/ \
$(MEDIASTREAMER_CFLAGS) \
$(ORTP_CFLAGS) \
$(STRICT_OPTIONS) $(LIBGTK_CFLAGS) $(LIBGTKMAC_CFLAGS) $(IPV6_CFLAGS) \
$(TUNNEL_CFLAGS)
$(TUNNEL_CFLAGS) \
$(SQLITE3_CFLAGS)
version_date.h: $(top_srcdir)/configure.ac

View file

@ -30,6 +30,7 @@ pt_BR: Rafael Caesar Lenzi &lt;rc_lenzi@yahoo.com.br&gt;
pl: Robert Nasiadek &lt;darkone@darkone.pl&gt;
cs: Petr Pisar &lt;petr.pisar@atlas.cz&gt;
hu: anonymous
he: Eli Zaretskii &lt;eliz@gnu.org&gt;
</property>
<property name="artists">Icons by kerosine.fr</property>
<signal name="response" handler="linphone_gtk_about_response"/>

View file

@ -82,7 +82,9 @@
<object class="GtkTreeView" id="logs_view">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="headers_visible">False</property>
<signal name="button-press-event" handler="linphone_gtk_call_log_button_pressed" swapped="no"/>
<signal name="row-activated" handler="linphone_gtk_history_row_activated" swapped="no"/>
</object>
</child>

View file

@ -59,7 +59,7 @@
<object class="GtkTable" id="table1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="n_rows">6</property>
<property name="n_rows">7</property>
<property name="n_columns">2</property>
<property name="homogeneous">True</property>
<child>
@ -134,7 +134,7 @@
<object class="GtkLabel" id="label4">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Media connectivity</property>
<property name="label" translatable="yes">Audio Media connectivity</property>
</object>
<packing>
<property name="top_attach">4</property>
@ -143,13 +143,7 @@
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<object class="GtkLabel" id="media_connectivity">
<object class="GtkLabel" id="audio_media_connectivity">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
@ -184,6 +178,52 @@
<property name="bottom_attach">4</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Video Media connectivity</property>
</object>
<packing>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="video_media_connectivity">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">5</property>
<property name="bottom_attach">6</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label5">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Round trip time</property>
</object>
<packing>
<property name="top_attach">6</property>
<property name="bottom_attach">7</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="round_trip_time">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
<property name="top_attach">6</property>
<property name="bottom_attach">7</property>
</packing>
</child>
</object>
</child>
</object>

View file

@ -19,13 +19,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "linphone.h"
static void fill_renderers(GtkTreeView *v){
GtkTreeViewColumn *c;
GtkCellRenderer *r=gtk_cell_renderer_pixbuf_new ();
GtkCellRenderer *r;
r=gtk_cell_renderer_pixbuf_new();
g_object_set(r,"stock-size",GTK_ICON_SIZE_BUTTON,NULL);
c=gtk_tree_view_column_new_with_attributes("icon",r,"stock-id",0,NULL);
c=gtk_tree_view_column_new_with_attributes("icon",r,"pixbuf",0,NULL);
gtk_tree_view_append_column (v,c);
r=gtk_cell_renderer_text_new ();
@ -33,51 +32,273 @@ static void fill_renderers(GtkTreeView *v){
gtk_tree_view_append_column (v,c);
}
void call_log_selection_changed(GtkTreeView *v){
GtkTreeSelection *select;
GtkTreeIter iter;
GtkTreeModel *model=NULL;
select = gtk_tree_view_get_selection(v);
if (select!=NULL){
if (gtk_tree_selection_get_selected (select, &model, &iter)){
GtkTreePath *path=gtk_tree_model_get_path(model,&iter);
gtk_tree_view_collapse_all(v);
gtk_tree_view_expand_row(v,path,TRUE);
gtk_tree_path_free(path);
}
}
}
void linphone_gtk_call_log_chat_selected(GtkWidget *w){
GtkTreeSelection *select;
GtkTreeIter iter;
select=gtk_tree_view_get_selection(GTK_TREE_VIEW(w));
if (select!=NULL){
GtkTreeModel *model=NULL;
if (gtk_tree_selection_get_selected (select,&model,&iter)){
gpointer pla;
LinphoneAddress *la;
gtk_tree_model_get(model,&iter,2,&pla,-1);
la=(LinphoneAddress*)pla;
if (la!=NULL){
linphone_gtk_friend_list_set_chat_conversation(la);
}
}
}
}
void linphone_gtk_call_log_add_contact(GtkWidget *w){
GtkTreeSelection *select;
GtkTreeIter iter;
select=gtk_tree_view_get_selection(GTK_TREE_VIEW(w));
if (select!=NULL){
GtkTreeModel *model=NULL;
if (gtk_tree_selection_get_selected (select,&model,&iter)){
gpointer pla;
LinphoneAddress *la;
LinphoneFriend *lf;
gtk_tree_model_get(model,&iter,2,&pla,-1);
la=(LinphoneAddress*)pla;
if (la!=NULL){
char *uri=linphone_address_as_string(la);
lf=linphone_friend_new_with_addr(uri);
linphone_gtk_show_contact(lf);
ms_free(uri);
}
}
}
}
static bool_t put_selection_to_uribar(GtkWidget *treeview){
GtkTreeSelection *sel;
sel=gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
if (sel!=NULL){
GtkTreeModel *model=NULL;
GtkTreeIter iter;
if (gtk_tree_selection_get_selected (sel,&model,&iter)){
char *tmp;
LinphoneAddress *la;
gtk_tree_model_get(model,&iter,2,&la,-1);
tmp=linphone_address_as_string(la);
if(tmp!=NULL)
gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"uribar")),tmp);
ms_free(tmp);
return TRUE;
}
}
return FALSE;
}
static void linphone_gtk_call_selected(GtkTreeView *treeview){
put_selection_to_uribar(GTK_WIDGET(treeview));
linphone_gtk_start_call(linphone_gtk_get_widget(gtk_widget_get_toplevel(GTK_WIDGET(treeview)),
"start_call"));
}
static GtkWidget *linphone_gtk_create_call_log_menu(GtkWidget *call_log){
GtkWidget *menu=gtk_menu_new();
GtkWidget *menu_item;
gchar *call_label=NULL;
gchar *text_label=NULL;
gchar *name=NULL;
GtkWidget *image;
GtkTreeSelection *select;
GtkTreeIter iter;
select=gtk_tree_view_get_selection(GTK_TREE_VIEW(call_log));
if (select!=NULL){
GtkTreeModel *model=NULL;
if (gtk_tree_selection_get_selected (select,&model,&iter)){
gpointer pla;
LinphoneAddress *la;
gtk_tree_model_get(model,&iter,2,&pla,-1);
la=(LinphoneAddress*)pla;
name=linphone_address_as_string(la);
call_label=g_strdup_printf(_("Call %s"),name);
text_label=g_strdup_printf(_("Send text to %s"),name);
g_free(name);
}
}
if (call_label){
menu_item=gtk_image_menu_item_new_with_label(call_label);
image=gtk_image_new_from_stock(GTK_STOCK_NETWORK,GTK_ICON_SIZE_MENU);
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),image);
gtk_widget_show(image);
gtk_widget_show(menu_item);
gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_call_selected,call_log);
}
if (text_label){
menu_item=gtk_image_menu_item_new_with_label(text_label);
image=gtk_image_new_from_stock(GTK_STOCK_NETWORK,GTK_ICON_SIZE_MENU);
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),image);
gtk_widget_show(image);
gtk_widget_show(menu_item);
gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_call_log_chat_selected,call_log);
}
menu_item=gtk_image_menu_item_new_from_stock(GTK_STOCK_ADD,NULL);
gtk_widget_show(menu_item);
gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_call_log_add_contact,call_log);
gtk_widget_show(menu);
gtk_menu_attach_to_widget(GTK_MENU(menu),call_log, NULL);
if (call_label) g_free(call_label);
if (text_label) g_free(text_label);
return menu;
}
gboolean linphone_gtk_call_log_popup_contact(GtkWidget *list, GdkEventButton *event){
GtkWidget *m=linphone_gtk_create_call_log_menu(list);
gtk_menu_popup (GTK_MENU (m), NULL, NULL, NULL, NULL,
event ? event->button : 0, event ? event->time : gtk_get_current_event_time());
return TRUE;
}
gboolean linphone_gtk_call_log_button_pressed(GtkWidget *widget, GdkEventButton *event){
if (event->button == 3 && event->type == GDK_BUTTON_PRESS){
return linphone_gtk_call_log_popup_contact(widget, event);
}
return FALSE;
}
void linphone_gtk_call_log_clear_missed_call(){
GtkWidget *mw=linphone_gtk_get_main_window();
GtkNotebook *notebook=GTK_NOTEBOOK(linphone_gtk_get_widget(mw,"viewswitch"));
GtkWidget *page=gtk_notebook_get_nth_page(notebook,0);
GtkWidget *box=gtk_hbox_new(FALSE,0);
GtkWidget *image=gtk_image_new_from_stock(GTK_STOCK_REFRESH,GTK_ICON_SIZE_MENU);
GtkWidget *l;
const gchar*text=gtk_label_get_text(GTK_LABEL(linphone_gtk_get_widget(mw,"label3")));
l=gtk_label_new(text);
gtk_box_pack_start(GTK_BOX(box),image,FALSE,FALSE,0);
gtk_box_pack_start(GTK_BOX(box),l,FALSE,FALSE,0);
gtk_notebook_set_tab_label(notebook,page,box);
gtk_widget_show_all(box);
}
gboolean linphone_gtk_call_log_reset_missed_call(GtkWidget *w, GdkEvent *event,gpointer user_data){
GtkWidget *mw=linphone_gtk_get_main_window();
GtkNotebook *notebook=GTK_NOTEBOOK(linphone_gtk_get_widget(mw,"viewswitch"));
gtk_notebook_set_current_page(notebook,0);
linphone_core_reset_missed_calls_count(linphone_gtk_get_core());
linphone_gtk_call_log_clear_missed_call();
return TRUE;
}
void linphone_gtk_call_log_display_missed_call(int nb){
GtkWidget *mw=linphone_gtk_get_main_window();
GtkNotebook *notebook=GTK_NOTEBOOK(linphone_gtk_get_widget(mw,"viewswitch"));
GtkWidget *page=gtk_notebook_get_nth_page(notebook,0);
GtkWidget *ebox=gtk_event_box_new();
GtkWidget *box=gtk_hbox_new(FALSE,0);
GtkWidget *image=gtk_image_new_from_stock(GTK_STOCK_REFRESH,GTK_ICON_SIZE_MENU);
GtkWidget *l;
gchar *buf;
buf=g_markup_printf_escaped(_("<b>Recent calls (%i)</b>"),nb);
l=gtk_label_new(NULL);
gtk_label_set_markup(GTK_LABEL(l),buf);
gtk_box_pack_start(GTK_BOX(box),image,FALSE,FALSE,0);
gtk_box_pack_start(GTK_BOX(box),l,FALSE,FALSE,0);
gtk_container_add(GTK_CONTAINER(ebox),box);
gtk_notebook_set_tab_label(notebook,page,ebox);
gtk_widget_add_events(ebox,GDK_BUTTON_PRESS_MASK);
g_signal_connect(G_OBJECT(ebox),"button_press_event",(GCallback)linphone_gtk_call_log_reset_missed_call,NULL);
gtk_widget_show_all(ebox);
}
void linphone_gtk_call_log_update(GtkWidget *w){
GtkTreeView *v=GTK_TREE_VIEW(linphone_gtk_get_widget(w,"logs_view"));
GtkListStore *store;
GtkTreeStore *store;
const MSList *logs;
GtkTreeSelection *select;
GtkWidget *notebook=linphone_gtk_get_widget(w,"viewswitch");
gint nb;
store=(GtkListStore*)gtk_tree_view_get_model(v);
store=(GtkTreeStore*)gtk_tree_view_get_model(v);
if (store==NULL){
store=gtk_list_store_new(3,G_TYPE_STRING,G_TYPE_STRING, G_TYPE_POINTER);
store=gtk_tree_store_new(3,GDK_TYPE_PIXBUF,G_TYPE_STRING,G_TYPE_POINTER,G_TYPE_STRING);
gtk_tree_view_set_model(v,GTK_TREE_MODEL(store));
g_object_unref(G_OBJECT(store));
fill_renderers(GTK_TREE_VIEW(linphone_gtk_get_widget(w,"logs_view")));
select=gtk_tree_view_get_selection(v);
gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE);
g_signal_connect_swapped(G_OBJECT(select),"changed",(GCallback)call_log_selection_changed,v);
g_signal_connect(G_OBJECT(notebook),"focus-tab",(GCallback)linphone_gtk_call_log_reset_missed_call,NULL);
g_signal_connect(G_OBJECT(v),"button-press-event",(GCallback)linphone_gtk_call_log_button_pressed,NULL);
// gtk_button_set_image(GTK_BUTTON(linphone_gtk_get_widget(w,"call_back_button")),
// create_pixmap (linphone_gtk_get_ui_config("callback_button","status-green.png")));
}
gtk_list_store_clear (store);
nb=linphone_core_get_missed_calls_count(linphone_gtk_get_core());
if(nb > 0)
linphone_gtk_call_log_display_missed_call(nb);
gtk_tree_store_clear (store);
for (logs=linphone_core_get_call_logs(linphone_gtk_get_core());logs!=NULL;logs=logs->next){
LinphoneCallLog *cl=(LinphoneCallLog*)logs->data;
GtkTreeIter iter;
LinphoneAddress *la=cl->dir==LinphoneCallIncoming ? cl->from : cl->to;
char *addr= linphone_address_as_string_uri_only (la);
GtkTreeIter iter, iter2;
const LinphoneAddress *la=linphone_call_log_get_dir(cl)==LinphoneCallIncoming ? linphone_call_log_get_from(cl) : linphone_call_log_get_to(cl);
char *addr= linphone_address_as_string(la);
const char *display;
gchar *logtxt, *minutes, *seconds;
gchar *logtxt, *headtxt, *minutes, *seconds;
gchar quality[20];
const char *status=NULL;
gchar *start_date=NULL;
LinphoneFriend *lf=NULL;
int duration=linphone_call_log_get_duration(cl);
time_t start_date_time=linphone_call_log_get_start_date(cl);
#if GLIB_CHECK_VERSION(2,26,0)
if (cl->start_date_time){
GDateTime *dt=g_date_time_new_from_unix_local(cl->start_date_time);
if (start_date_time){
GDateTime *dt=g_date_time_new_from_unix_local(start_date_time);
start_date=g_date_time_format(dt,"%c");
g_date_time_unref(dt);
}
#else
start_date=g_strdup(ctime(&start_date_time));
#endif
display=linphone_address_get_display_name (la);
lf=linphone_core_get_friend_by_address(linphone_gtk_get_core(),addr);
if(lf != NULL){
la=linphone_friend_get_address(lf);
display=linphone_address_get_display_name(la);
} else {
display=linphone_address_get_display_name(la);
}
if (display==NULL){
display=linphone_address_get_username (la);
if (display==NULL)
if (display==NULL){
display=linphone_address_get_domain (la);
}
}
if (cl->quality!=-1){
snprintf(quality,sizeof(quality),"%.1f",cl->quality);
}
switch(cl->status){
if (linphone_call_log_get_quality(cl)!=-1){
snprintf(quality,sizeof(quality),"%.1f",linphone_call_log_get_quality(cl));
}else snprintf(quality,sizeof(quality)-1,"%s",_("n/a"));
switch(linphone_call_log_get_status(cl)){
case LinphoneCallAborted:
status=_("Aborted");
break;
@ -91,54 +312,39 @@ void linphone_gtk_call_log_update(GtkWidget *w){
break;
}
minutes=g_markup_printf_escaped(
ngettext("%i minute", "%i minutes", cl->duration/60),
cl->duration/60);
ngettext("%i minute", "%i minutes", duration/60),
duration/60);
seconds=g_markup_printf_escaped(
ngettext("%i second", "%i seconds", cl->duration%60),
cl->duration%60);
if (status==NULL) logtxt=g_markup_printf_escaped(
_("<big><b>%s</b></big>\t<small><i>%s</i>\t"
"<i>Quality: %s</i></small>\n%s\t%s %s\t"),
display, addr, cl->quality!=-1 ? quality : _("n/a"),
start_date ? start_date : cl->start_date, minutes, seconds);
else logtxt=g_markup_printf_escaped(
_("<big><b>%s</b></big>\t<small><i>%s</i></small>\t"
"\n%s\t%s"),
display, addr,
start_date ? start_date : cl->start_date, status);
ngettext("%i second", "%i seconds", duration%60),
duration%60);
if (status==NULL) {
headtxt=g_markup_printf_escaped(_("<big><b>%s</b></big>\t%s"),display,start_date ? start_date : "");
logtxt=g_markup_printf_escaped(
_("<small><i>%s</i>\t"
"<i>Quality: %s</i></small>\n%s\t%s\t"),
addr, quality, minutes, seconds);
} else {
headtxt=g_markup_printf_escaped(_("<big><b>%s</b></big>\t%s"),display,start_date ? start_date : "");
logtxt=g_markup_printf_escaped(
_("<small><i>%s</i></small>\t"
"\n%s"),addr, status);
}
g_free(minutes);
g_free(seconds);
if (start_date) g_free(start_date);
gtk_list_store_append (store,&iter);
gtk_list_store_set (store,&iter,
0, cl->dir==LinphoneCallOutgoing ? GTK_STOCK_GO_UP : GTK_STOCK_GO_DOWN,
1, logtxt,2,la,-1);
gtk_tree_store_append (store,&iter,NULL);
GdkPixbuf *incoming = create_pixbuf("call_status_incoming.png");
GdkPixbuf *outgoing = create_pixbuf("call_status_outgoing.png");
gtk_tree_store_set (store,&iter,
0, linphone_call_log_get_dir(cl)==LinphoneCallOutgoing ? outgoing : incoming,
1, headtxt,2,la,-1);
gtk_tree_store_append (store,&iter2,&iter);
gtk_tree_store_set (store,&iter2,1,logtxt,2,la,-1);
ms_free(addr);
g_free(logtxt);
g_free(headtxt);
}
}
static bool_t put_selection_to_uribar(GtkWidget *treeview){
GtkTreeSelection *sel;
sel=gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
if (sel!=NULL){
GtkTreeModel *model=NULL;
GtkTreeIter iter;
if (gtk_tree_selection_get_selected (sel,&model,&iter)){
gpointer pla;
LinphoneAddress *la;
char *tmp;
gtk_tree_model_get(model,&iter,2,&pla,-1);
la=(LinphoneAddress*)pla;
tmp=linphone_address_as_string (la);
gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"uribar")),tmp);
ms_free(tmp);
return TRUE;
}
}
return FALSE;
}
void linphone_gtk_history_row_activated(GtkWidget *treeview){
@ -154,6 +360,7 @@ void linphone_gtk_history_row_selected(GtkWidget *treeview){
void linphone_gtk_clear_call_logs(GtkWidget *button){
linphone_core_clear_call_logs (linphone_gtk_get_core());
linphone_gtk_call_log_clear_missed_call();
linphone_gtk_call_log_update(gtk_widget_get_toplevel(button));
}
@ -177,8 +384,6 @@ void linphone_gtk_call_log_response(GtkWidget *w, guint response_id){
gtk_widget_destroy(w);
}
GtkWidget * linphone_gtk_show_call_logs(void){
GtkWidget *mw=linphone_gtk_get_main_window();
@ -193,5 +398,4 @@ GtkWidget * linphone_gtk_show_call_logs(void){
linphone_gtk_call_log_update(w);
}else gtk_window_present(GTK_WINDOW(w));
return w;
}
}

View file

@ -23,21 +23,72 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <gtkosxapplication.h>
#endif
#define NB_MSG_HIST 250
#define CONFIG_FILE ".linphone-history.db"
const char *linphone_gtk_message_storage_get_db_file(const char *filename){
const int path_max=1024;
static char *db_file=NULL;
if (db_file) return db_file;
db_file=(char *)malloc(path_max*sizeof(char));
if (filename==NULL) filename=CONFIG_FILE;
/*try accessing a local file first if exists*/
if (access(CONFIG_FILE,F_OK)==0){
snprintf(db_file,path_max,"%s",filename);
}else{
#ifdef WIN32
const char *appdata=getenv("APPDATA");
if (appdata){
snprintf(db_file,path_max,"%s\\%s",appdata,LINPHONE_CONFIG_DIR);
CreateDirectory(db_file,NULL);
snprintf(db_file,path_max,"%s\\%s\\%s",appdata,LINPHONE_CONFIG_DIR,filename);
}
#else
const char *home=getenv("HOME");
if (home==NULL) home=".";
snprintf(db_file,path_max,"%s/%s",home,filename);
#endif
}
return db_file;
}
void linphone_gtk_quit_chatroom(LinphoneChatRoom *cr) {
GtkWidget *main_window=linphone_gtk_get_main_window ();
GtkWidget *nb=linphone_gtk_get_widget(main_window,"viewswitch");
GtkWidget *friendlist=linphone_gtk_get_widget(main_window,"contact_list");
GtkWidget *w=g_object_get_data(G_OBJECT(friendlist),"chatview");
int idx = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"idx"));
gchar *from;
GHashTable *table=g_object_get_data(G_OBJECT(w),"table");
g_return_if_fail(w!=NULL);
gtk_notebook_remove_page (GTK_NOTEBOOK(nb),idx);
linphone_gtk_update_chat_picture(FALSE);
gtk_notebook_remove_page(GTK_NOTEBOOK(nb),gtk_notebook_page_num(GTK_NOTEBOOK(nb),w));
linphone_chat_room_mark_as_read(cr);
linphone_gtk_friend_list_update_chat_picture();
g_object_set_data(G_OBJECT(friendlist),"chatview",NULL);
g_object_set_data(G_OBJECT(w),"from_message",NULL);
from=g_object_get_data(G_OBJECT(w),"from_message");
if (from){
g_object_set_data(G_OBJECT(w),"from_message",NULL);
g_free(from);
}
g_hash_table_destroy(table);
g_object_set_data(G_OBJECT(w),"cr",NULL);
g_object_set_data(G_OBJECT(friendlist),"from",NULL);
gtk_widget_destroy(w);
}
const char* get_display_name(const LinphoneAddress *from){
const char *display;
display=linphone_address_get_display_name(from);
if (display==NULL || display[0]=='\0') {
display=linphone_address_get_username(from);
}
return display;
}
GtkWidget *create_tab_chat_header(LinphoneChatRoom *cr,const LinphoneAddress *uri){
GtkWidget *w=gtk_hbox_new (FALSE,0);
GtkWidget *i=create_pixmap ("chat.png");
@ -49,12 +100,7 @@ GtkWidget *create_tab_chat_header(LinphoneChatRoom *cr,const LinphoneAddress *ur
gtk_button_set_relief(GTK_BUTTON(b),GTK_RELIEF_NONE);
gtk_widget_set_size_request(b,25,20);
g_signal_connect_swapped(G_OBJECT(b),"clicked",G_CALLBACK(linphone_gtk_quit_chatroom),cr);
const char *display=linphone_address_get_display_name(uri);
if (display==NULL || display[0]=='\0') {
display=linphone_address_get_username(uri);
}
l=gtk_label_new (display);
l=gtk_label_new(get_display_name(uri));
gtk_box_pack_start (GTK_BOX(w),i,FALSE,FALSE,0);
gtk_box_pack_start (GTK_BOX(w),l,FALSE,FALSE,0);
gtk_box_pack_end(GTK_BOX(w),b,TRUE,TRUE,0);
@ -75,72 +121,95 @@ void udpate_tab_chat_header(GtkWidget *chat_view,const LinphoneAddress *uri,Linp
gtk_button_set_relief(GTK_BUTTON(b),GTK_RELIEF_NONE);
gtk_widget_set_size_request(b,25,20);
g_signal_connect_swapped(G_OBJECT(b),"clicked",G_CALLBACK(linphone_gtk_quit_chatroom),cr);
const char *display=linphone_address_get_display_name(uri);
if (display==NULL || display[0]=='\0') {
display=linphone_address_get_username(uri);
}
l=gtk_label_new (display);
l=gtk_label_new (get_display_name(uri));
gtk_box_pack_start (GTK_BOX(w),i,FALSE,FALSE,0);
gtk_box_pack_start (GTK_BOX(w),l,FALSE,FALSE,0);
gtk_box_pack_end(GTK_BOX(w),b,TRUE,TRUE,0);
gtk_notebook_set_tab_label(notebook,chat_view,w);
gtk_widget_show_all(w);
}
void linphone_gtk_push_text(GtkWidget *w, const LinphoneAddress *from, const char *message, gboolean me,LinphoneChatRoom *cr){
GtkTextView *text=GTK_TEXT_VIEW(linphone_gtk_get_widget(w,"textview"));
GtkTextBuffer *buffer=gtk_text_view_get_buffer(text);
GtkTextIter iter,begin,end;
gtk_text_buffer_get_start_iter(buffer,&begin);
static gboolean scroll_to_end(GtkTextView *w){
GtkTextBuffer *buffer=gtk_text_view_get_buffer(w);
GtkTextIter iter;
gtk_text_buffer_get_end_iter(buffer,&iter);
GtkTextMark *mark=gtk_text_buffer_create_mark(buffer,NULL,&iter,FALSE);
gtk_text_view_scroll_mark_onscreen(w,mark);
return FALSE;
}
void linphone_gtk_push_text(GtkWidget *w, const LinphoneAddress *from,
gboolean me,LinphoneChatRoom *cr,LinphoneChatMessage *msg, gboolean hist){
GtkTextView *text=GTK_TEXT_VIEW(linphone_gtk_get_widget(w,"textview"));
GtkTextBuffer *buffer=gtk_text_view_get_buffer(text);
GtkTextIter iter,begin;
int off;
char *from_str=linphone_address_as_string_uri_only(from);
gchar *from_message=(gchar *)g_object_get_data(G_OBJECT(w),"from_message");
GHashTable *table=(GHashTable*)g_object_get_data(G_OBJECT(w),"table");
time_t t;
char buf[80];
time_t tnow;
struct tm *tm;
int tnow_day;
int tnow_year;
gtk_text_buffer_get_start_iter(buffer,&begin);
gtk_text_buffer_get_end_iter(buffer,&iter);
off=gtk_text_iter_get_offset(&iter);
//GList *list=g_object_get_data(G_OBJECT(w),"list");
if(g_strcmp0((char *)g_object_get_data(G_OBJECT(w),"from_message"),linphone_address_as_string(from))!=0){
if(g_strcmp0(from_message,from_str)!=0){
gtk_text_buffer_get_iter_at_offset(buffer,&iter,off);
const char *display=linphone_address_get_display_name(from);
if (display==NULL || display[0]=='\0') {
display=linphone_address_get_username(from);
}
gtk_text_buffer_get_end_iter(buffer,&iter);
gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,display,-1,"bold",me ? "left" : "left",NULL);
gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,get_display_name(from),-1,"bold",me ? "bg":NULL,NULL);
gtk_text_buffer_get_end_iter(buffer,&iter);
gtk_text_buffer_insert_with_tags_by_name(buffer,&iter," : ",-1,"bold",me ? "bg":NULL,NULL);
gtk_text_buffer_get_end_iter(buffer,&iter);
gtk_text_buffer_insert(buffer,&iter,"\n",-1);
g_object_set_data(G_OBJECT(w),"from_message",linphone_address_as_string(from));
g_free(from_message);
g_object_set_data(G_OBJECT(w),"from_message",g_strdup(from_str));
}
gtk_text_buffer_get_end_iter(buffer,&iter);
gtk_text_buffer_get_iter_at_offset(buffer,&begin,off);
gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,linphone_chat_message_get_text(msg),-1,"margin",me ? "bg":NULL,NULL);
gtk_text_buffer_get_end_iter(buffer,&iter);
gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,message,-1,me ? "left" : "left",NULL);
gtk_text_buffer_get_end_iter(buffer,&iter);
gtk_text_buffer_insert(buffer,&iter,"\n",-1);
gtk_text_buffer_get_bounds (buffer, &begin, &end);
GHashTable *hash=(GHashTable *)g_object_get_data(G_OBJECT(linphone_gtk_get_main_window()),"history");
if(me){
g_hash_table_insert(hash,linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr)),
(gpointer)gtk_text_buffer_get_text(buffer,&begin,&end,FALSE));
} else {
g_hash_table_insert(hash,linphone_address_as_string_uri_only(from),
(gpointer)gtk_text_buffer_get_text(buffer,&begin,&end,FALSE));
}
g_object_set_data(G_OBJECT(linphone_gtk_get_main_window()),"history",hash);
/*if(me){
gtk_text_buffer_get_end_iter(buffer,&iter);
list=g_list_append(list,GINT_TO_POINTER(gtk_text_iter_get_line(&iter)));
gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,"Message in progress.. ",-1,
"italic","right","small","font_grey",NULL);
gtk_text_buffer_get_end_iter(buffer,&iter);
gtk_text_buffer_insert(buffer,&iter,"\n",-1);
g_object_set_data(G_OBJECT(w),"list",list);
}*/
GtkTextMark *mark=gtk_text_buffer_create_mark(buffer,NULL,&iter,FALSE);
gtk_text_view_scroll_mark_onscreen(text,mark);
gtk_text_buffer_get_end_iter(buffer,&iter);
t=linphone_chat_message_get_time(msg);
switch (linphone_chat_message_get_state (msg)){
case LinphoneChatMessageStateInProgress:
{
g_hash_table_insert(table,(gpointer)msg,GINT_TO_POINTER(gtk_text_iter_get_line(&iter)));
gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,"Sending .. ",-1,
"right","small","italic","font_grey","bg",NULL);
g_object_set_data(G_OBJECT(w),"table",table);
break;
}
case LinphoneChatMessageStateDelivered:
{
tnow=time(NULL);
tm=localtime(&tnow);
tnow_day=tm->tm_yday;
tnow_year=tm->tm_year;
tm=localtime(&t);
if(tnow_day != tm->tm_yday || (tnow_day == tm->tm_yday && tnow_year != tm->tm_year)) {
strftime(buf,80,"%a %x, %H:%M",tm);
} else {
strftime(buf,80,"%H:%M",tm);
}
gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,buf,-1,
"right","small","italic","font_grey",me ? "bg":NULL,NULL);
break;
}
case LinphoneChatMessageStateNotDelivered:
gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,"Message not sent",-1,
"right","small","italic","font_grey",me ? "bg":NULL,NULL);
break;
default : gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,"Sending ..",-1,
"right","small","italic","font_grey",me ? "bg":NULL,NULL);
}
gtk_text_buffer_get_end_iter(buffer,&iter);
gtk_text_buffer_insert(buffer,&iter,"\n",-1);
g_idle_add((GSourceFunc)scroll_to_end,text);
ms_free(from_str);
}
const LinphoneAddress* linphone_gtk_get_used_identity(){
@ -151,13 +220,11 @@ const LinphoneAddress* linphone_gtk_get_used_identity(){
else return linphone_core_get_primary_contact_parsed(lc);
}
/* function in dev for displaying ack*/
void update_chat_state_message(LinphoneChatMessageState state){
/* GtkWidget *main_window=linphone_gtk_get_main_window();
GtkWidget *friendlist=linphone_gtk_get_widget(main_window,"contact_list");
void update_chat_state_message(LinphoneChatMessageState state,LinphoneChatMessage *msg){
GtkWidget *main_window=linphone_gtk_get_main_window();
GtkWidget *friendlist=linphone_gtk_get_widget(main_window,"contact_list");
GtkWidget *page=(GtkWidget*)g_object_get_data(G_OBJECT(friendlist),"chatview");
GList *list=g_object_get_data(G_OBJECT(page),"list");
GHashTable *table=(GHashTable*)g_object_get_data(G_OBJECT(page),"table");
if(page!=NULL){
GtkTextView *text=GTK_TEXT_VIEW(linphone_gtk_get_widget(page,"textview"));
@ -165,105 +232,158 @@ void update_chat_state_message(LinphoneChatMessageState state){
GtkTextIter iter;
GtkTextIter end;
GtkTextIter start;
gtk_text_buffer_get_iter_at_line(b,&iter,
GPOINTER_TO_INT(g_list_nth_data(list,0)));
if(gtk_text_iter_get_chars_in_line(&iter) >0) {
gtk_text_buffer_get_iter_at_line_offset(b,&start,
GPOINTER_TO_INT(g_list_nth_data(list,0)),
gtk_text_iter_get_chars_in_line(&iter)-1);
}else {
gtk_text_buffer_get_iter_at_line_offset(b,&start,
GPOINTER_TO_INT(g_list_nth_data(list,0)),0);
}
gtk_text_buffer_get_iter_at_line_offset(b,&end,
GPOINTER_TO_INT(g_list_nth_data(list,0)),0);
gtk_text_buffer_delete(b,&start,&end);
gtk_text_buffer_get_iter_at_line(b,&iter,GPOINTER_TO_INT(g_list_nth_data(list,0)));
gchar *result;
gint line;
line=GPOINTER_TO_INT(g_hash_table_lookup(table,msg));
gtk_text_buffer_get_iter_at_line(b,&iter,line);
if(gtk_text_iter_get_chars_in_line(&iter) >0) {
gtk_text_buffer_get_iter_at_line_offset(b,&start,line,
gtk_text_iter_get_chars_in_line(&iter)-1);
}else{
gtk_text_buffer_get_iter_at_line_offset(b,&start,line,0);
}
gtk_text_buffer_get_iter_at_line_offset(b,&end,line,0);
gtk_text_buffer_delete(b,&start,&end);
gtk_text_buffer_get_iter_at_line(b,&iter,line);
switch (state) {
case LinphoneChatMessageStateInProgress:
result="Message in progress.. ";
result="Sending ";
break;
case LinphoneChatMessageStateDelivered:
result="Message delivered ";
{
time_t t=time(NULL);
struct tm *tm=localtime(&t);
char buf[80];
strftime(buf,80,"%H:%M",tm);
result=buf;
break;
}
case LinphoneChatMessageStateNotDelivered:
result="Message not delivered ";
result="Message not sent";
break;
default : result="Message in progress.. ";
default : result="Sending ..";
}
gtk_text_buffer_insert_with_tags_by_name(b,&iter,result,-1,
"italic","right","small","font_grey",NULL);
list=g_list_remove(list,g_list_nth_data(list,0));
g_object_set_data(G_OBJECT(page),"list",list);
} */
"right","small","italic","font_grey","bg",NULL);
g_hash_table_remove(table,msg);
g_object_set_data(G_OBJECT(page),"table",table);
}
}
static void on_chat_state_changed(LinphoneChatMessage *msg, LinphoneChatMessageState state, void *user_pointer){
g_message("chat message state is %s",linphone_chat_message_state_to_string(state));
update_chat_state_message(state);
update_chat_state_message(state,msg);
}
void linphone_gtk_send_text(){
GtkWidget *main_window=linphone_gtk_get_main_window();
GtkWidget *main_window=linphone_gtk_get_main_window();
GtkWidget *friendlist=linphone_gtk_get_widget(main_window,"contact_list");
GtkWidget *w=(GtkWidget*)g_object_get_data(G_OBJECT(friendlist),"chatview");
GtkWidget *w=(GtkWidget*)g_object_get_data(G_OBJECT(friendlist),"chatview");
GtkWidget *entry=linphone_gtk_get_widget(w,"text_entry");
const gchar *entered;
LinphoneChatRoom *cr=g_object_get_data(G_OBJECT(w),"cr");
entered=gtk_entry_get_text(GTK_ENTRY(entry));
if (strlen(entered)>0) {
LinphoneChatMessage *msg;
linphone_gtk_push_text(w,
linphone_gtk_get_used_identity(),
entered,TRUE,cr);
msg=linphone_chat_room_create_message(cr,entered);
linphone_chat_room_send_message2(cr,msg,on_chat_state_changed,NULL);
linphone_gtk_push_text(w,linphone_chat_message_get_from(msg),
TRUE,cr,msg,FALSE);
gtk_entry_set_text(GTK_ENTRY(entry),"");
}
}
static void linphone_gtk_chat_message_destroy(LinphoneChatMessage *msg){
linphone_chat_message_destroy(msg);
}
void linphone_gtk_free_list(MSList *messages){
ms_list_for_each(messages,(void (*)(void*))linphone_gtk_chat_message_destroy);
ms_list_free(messages);
}
void display_history_message(GtkWidget *chat_view,MSList *messages,const LinphoneAddress *with){
if(messages != NULL){
MSList *it;
char *from_str;
char *with_str;
gchar *tmp;
for(it=messages;it!=NULL;it=it->next){
LinphoneChatMessage *msg=(LinphoneChatMessage *)it->data;
from_str=linphone_address_as_string_uri_only(linphone_chat_message_get_from(msg));
with_str=linphone_address_as_string_uri_only(with);
linphone_gtk_push_text(chat_view,strcmp(from_str,with_str)==0? with :
linphone_chat_message_get_from(msg),
strcmp(from_str,with_str)==0? FALSE : TRUE,
linphone_chat_message_get_chat_room(msg),msg,TRUE);
}
tmp=g_object_get_data(G_OBJECT(chat_view),"from_message");
if (tmp){
g_object_set_data(G_OBJECT(chat_view),"from_message",NULL);
g_free(tmp);
}
ms_free(from_str);
ms_free(with_str);
linphone_gtk_free_list(messages);
}
}
void linphone_gtk_chat_add_contact(const LinphoneAddress *addr){
LinphoneFriend *lf=NULL;
char *uri=linphone_address_as_string(addr);
lf=linphone_friend_new_with_addr(uri);
ms_free(uri);
char *fixed_uri=NULL;
gboolean show_presence=FALSE;
linphone_friend_set_inc_subscribe_policy(lf,LinphoneSPDeny);
linphone_friend_send_subscribe(lf,show_presence);
linphone_core_interpret_friend_uri(linphone_gtk_get_core(),uri,&fixed_uri);
if (fixed_uri==NULL){
linphone_gtk_display_something(GTK_MESSAGE_WARNING,_("Invalid sip contact !"));
return ;
}
linphone_friend_set_addr(lf,addr);
linphone_core_add_friend(linphone_gtk_get_core(),lf);
ms_free(fixed_uri);
linphone_gtk_show_friends();
}
GtkWidget* linphone_gtk_init_chatroom(LinphoneChatRoom *cr, const LinphoneAddress *with){
GtkWidget *chat_view=linphone_gtk_create_widget("main","chatroom_frame");
GtkWidget *main_window=linphone_gtk_get_main_window ();
GHashTable *hash=g_object_get_data(G_OBJECT(main_window),"history");
GtkNotebook *notebook=(GtkNotebook *)linphone_gtk_get_widget(main_window,"viewswitch");
GtkWidget *text=linphone_gtk_get_widget(chat_view,"textview");
GdkColor color;
GdkColor colorb;
int idx;
GtkWidget *button;
GtkWidget *entry;
MSList *messages;
GHashTable *table;
char *with_str;
color.red = 32512;
color.green = 32512;
color.blue = 32512;
colorb.red = 56832;
colorb.green = 60928;
colorb.blue = 61952;
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW(text),GTK_WRAP_WORD);
gtk_text_view_set_editable (GTK_TEXT_VIEW(text),FALSE);
gtk_notebook_append_page (notebook,chat_view,create_tab_chat_header(cr,with));
with_str=linphone_address_as_string_uri_only(with);
gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text),GTK_WRAP_WORD_CHAR);
gtk_text_view_set_editable(GTK_TEXT_VIEW(text),FALSE);
gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(text),FALSE);
gtk_notebook_append_page(notebook,chat_view,create_tab_chat_header(cr,with));
idx = gtk_notebook_page_num(notebook, chat_view);
gtk_notebook_set_current_page(notebook, idx);
gtk_widget_show(chat_view);
table=g_hash_table_new_full(g_direct_hash,g_direct_equal,NULL,NULL);
g_object_set_data(G_OBJECT(chat_view),"cr",cr);
g_object_set_data(G_OBJECT(chat_view),"idx",GINT_TO_POINTER(idx));
g_object_set_data(G_OBJECT(chat_view),"from_message",NULL);
g_object_set_data(G_OBJECT(chat_view),"from_chatroom",linphone_address_as_string_uri_only(with));
GList *list=NULL;
g_object_set_data(G_OBJECT(chat_view),"list",list);
gchar *buf=g_hash_table_lookup(hash,linphone_address_as_string_uri_only(with));
if(buf != NULL){
GtkTextIter start;
GtkTextIter end;
GtkTextBuffer *text_buffer;
text_buffer=gtk_text_view_get_buffer(GTK_TEXT_VIEW(text));
gtk_text_buffer_get_bounds(text_buffer, &start, &end);
gtk_text_buffer_delete (text_buffer, &start, &end);
gtk_text_buffer_insert(text_buffer,&start,buf,-1);
}
g_object_set_data(G_OBJECT(chat_view),"table",table);
gtk_text_buffer_create_tag(gtk_text_view_get_buffer(GTK_TEXT_VIEW(text)),
"right","justification", GTK_JUSTIFY_RIGHT,NULL);
gtk_text_buffer_create_tag(gtk_text_view_get_buffer(GTK_TEXT_VIEW(text)),
@ -273,52 +393,61 @@ GtkWidget* linphone_gtk_init_chatroom(LinphoneChatRoom *cr, const LinphoneAddres
gtk_text_buffer_create_tag(gtk_text_view_get_buffer(GTK_TEXT_VIEW(text)),
"italic","style", PANGO_STYLE_ITALIC,NULL);
gtk_text_buffer_create_tag(gtk_text_view_get_buffer(GTK_TEXT_VIEW(text)),
"small","size",8*PANGO_SCALE,NULL);
"small","size",9*PANGO_SCALE,NULL);
gtk_text_buffer_create_tag(gtk_text_view_get_buffer(GTK_TEXT_VIEW(text)),
"font_grey","foreground-gdk",&color,NULL);
GtkWidget *button = linphone_gtk_get_widget(chat_view,"send");
gtk_text_buffer_create_tag(gtk_text_view_get_buffer(GTK_TEXT_VIEW(text)),
"margin","indent",10,NULL);
gtk_text_buffer_create_tag(gtk_text_view_get_buffer(GTK_TEXT_VIEW(text)),
"bg","paragraph-background-gdk",&colorb,NULL);
messages = linphone_chat_room_get_history(cr,NB_MSG_HIST);
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);
GtkWidget *entry = linphone_gtk_get_widget(chat_view,"text_entry");
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(G_OBJECT(notebook),"switch_page",(GCallback)linphone_gtk_notebook_tab_select,NULL);
ms_free(with_str);
return chat_view;
}
LinphoneChatRoom * linphone_gtk_create_chatroom(const LinphoneAddress *with){
LinphoneChatRoom *cr=linphone_core_create_chat_room(linphone_gtk_get_core(),linphone_address_as_string(with));
if (!cr) return NULL;
char *tmp=linphone_address_as_string(with);
LinphoneChatRoom *cr=linphone_core_create_chat_room(linphone_gtk_get_core(),tmp);
ms_free(tmp);
return cr;
}
void linphone_gtk_load_chatroom(LinphoneChatRoom *cr,const LinphoneAddress *uri,GtkWidget *chat_view){
GtkWidget *main_window=linphone_gtk_get_main_window ();
GHashTable *hash=g_object_get_data(G_OBJECT(main_window),"history");
if(g_strcmp0((char *)g_object_get_data(G_OBJECT(chat_view),"from_chatroom"),
linphone_address_as_string_uri_only(uri))!=0)
{
GtkTextView *text_view=GTK_TEXT_VIEW(linphone_gtk_get_widget(chat_view,"textview"));
GtkTextIter start;
GtkTextIter end;
gchar *buf=g_hash_table_lookup(hash,linphone_address_as_string_uri_only(uri));
GtkTextBuffer *text_buffer;
text_buffer=gtk_text_view_get_buffer(text_view);
gtk_text_buffer_get_bounds(text_buffer, &start, &end);
g_object_set_data(G_OBJECT(chat_view),"cr",cr);
gtk_text_buffer_delete (text_buffer, &start, &end);
if(buf!=NULL){
gtk_text_buffer_insert_with_tags_by_name(text_buffer,&start,buf,-1,"font_grey",NULL);
GtkTextMark *mark=gtk_text_buffer_create_mark(text_buffer, NULL, &start, FALSE);
gtk_text_view_scroll_to_mark(text_view,mark, 0, FALSE, 0, 0);
}
LinphoneChatRoom *cr2=(LinphoneChatRoom *)g_object_get_data(G_OBJECT(chat_view),"cr");
const LinphoneAddress *from=linphone_chat_room_get_peer_address(cr2);
char *from_str=linphone_address_as_string_uri_only(from);
char *uri_str=linphone_address_as_string(uri);
char *uri_only=linphone_address_as_string_uri_only(uri);
MSList *messages=NULL;
if(g_strcmp0(from_str,uri_only)!=0){
GtkTextView *text_view=GTK_TEXT_VIEW(linphone_gtk_get_widget(chat_view,"textview"));
GtkTextIter start;
GtkTextIter end;
GtkTextBuffer *text_buffer;
text_buffer=gtk_text_view_get_buffer(text_view);
gtk_text_buffer_get_bounds(text_buffer, &start, &end);
gtk_text_buffer_delete (text_buffer, &start, &end);
udpate_tab_chat_header(chat_view,uri,cr);
g_object_set_data(G_OBJECT(chat_view),"cr",cr);
g_object_set_data(G_OBJECT(chat_view),"from_chatroom",linphone_address_as_string_uri_only(uri));
g_object_set_data(G_OBJECT(chat_view),"from_message",linphone_address_as_string_uri_only(uri));
g_object_set_data(G_OBJECT(linphone_gtk_get_widget(main_window,"contact_list")),"chatview",(gpointer)chat_view);
messages=linphone_chat_room_get_history(cr,NB_MSG_HIST);
g_object_set_data(G_OBJECT(chat_view),"from_message",g_strdup(uri_str));
display_history_message(chat_view,messages,uri);
gtk_text_buffer_get_end_iter(text_buffer,&end);
gtk_text_view_scroll_to_iter(text_view,&end,0,FALSE,1.0,0);
}
ms_free(from_str);
ms_free(uri_str);
ms_free(uri_only);
}
void linphone_gtk_chat_destroyed(GtkWidget *w){
@ -326,40 +455,54 @@ void linphone_gtk_chat_destroyed(GtkWidget *w){
linphone_chat_room_destroy(cr);
}
void linphone_gtk_chat_close(GtkWidget *button){
GtkWidget *w=gtk_widget_get_toplevel(button);
gtk_widget_destroy(w);
}
void linphone_gtk_text_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddress *from, const char *message){
void linphone_gtk_text_received ( LinphoneCore *lc, LinphoneChatRoom *room,
LinphoneChatMessage *msg ) {
GtkWidget *main_window=linphone_gtk_get_main_window();
GtkWidget *friendlist=linphone_gtk_get_widget(main_window,"contact_list");
GtkWidget *w;
GtkWidget *friendlist=linphone_gtk_get_widget ( main_window,"contact_list" );
GtkWidget *w;
gboolean send=TRUE;
/*GtkNotebook *notebook= ( GtkNotebook * ) linphone_gtk_get_widget ( main_window,"viewswitch" );*/
char *from=linphone_address_as_string ( linphone_chat_message_get_from ( msg ) );
w=(GtkWidget*)g_object_get_data(G_OBJECT(friendlist),"chatview");
if(w!=NULL){
linphone_gtk_load_chatroom(room,from,w);
} else {
w=linphone_gtk_init_chatroom(room,from);
g_object_set_data(G_OBJECT(friendlist),"chatview",(gpointer)w);
}
#ifdef HAVE_GTK_OSX
/* Notified when a new message is sent */
linphone_gtk_status_icon_set_blinking(TRUE);
#else
if(!gtk_window_is_active(GTK_WINDOW(main_window))){
if(!GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"is_notified"))){
linphone_gtk_notify(NULL,message);
g_object_set_data(G_OBJECT(w),"is_notified",GINT_TO_POINTER(TRUE));
w= ( GtkWidget* ) g_object_get_data ( G_OBJECT ( friendlist ),"chatview" );
if ( w!=NULL ) {
char *from_chatview= ( char * ) g_object_get_data ( G_OBJECT ( friendlist ),"from" );
if ( g_strcmp0 ( from,from_chatview ) ==0 ) {
send=TRUE;
} else {
g_object_set_data(G_OBJECT(w),"is_notified",GINT_TO_POINTER(FALSE));
if ( !linphone_gtk_friend_list_is_contact ( linphone_chat_message_get_from ( msg ) ) ) {
linphone_gtk_chat_add_contact ( linphone_chat_message_get_from ( msg ) );
}
send=FALSE;
}
} else {
send=FALSE;
if ( !linphone_gtk_friend_list_is_contact ( linphone_chat_message_get_from ( msg ) ) ) {
linphone_gtk_chat_add_contact ( linphone_chat_message_get_from ( msg ) );
}
w=linphone_gtk_init_chatroom ( room,linphone_chat_message_get_from ( msg ) );
g_object_set_data ( G_OBJECT ( friendlist ),"chatview", ( gpointer ) w );
g_object_set_data ( G_OBJECT ( friendlist ),"from",from );
}
#ifdef HAVE_GTK_OSX
/* Notified when a new message is sent */
linphone_gtk_status_icon_set_blinking ( TRUE );
#else
if ( !gtk_window_is_active ( GTK_WINDOW ( main_window ) ) ) {
if ( !GPOINTER_TO_INT ( g_object_get_data ( G_OBJECT ( w ),"is_notified" ) ) ) {
linphone_gtk_notify ( NULL,linphone_chat_message_get_text ( msg ) );
g_object_set_data ( G_OBJECT ( w ),"is_notified",GINT_TO_POINTER ( TRUE ) );
} else {
g_object_set_data ( G_OBJECT ( w ),"is_notified",GINT_TO_POINTER ( FALSE ) );
}
}
#endif
linphone_gtk_push_text(w,from,message,FALSE,room);
//linphone_gtk_update_chat_picture(TRUE);
//gtk_window_present(GTK_WINDOW(w));
/*gtk_window_set_urgency_hint(GTK_WINDOW(w),TRUE);*/
#endif
if ( send ) {
linphone_gtk_push_text ( w,linphone_chat_message_get_from ( msg ),
FALSE,room,msg,FALSE );
}
linphone_gtk_show_friends();
}

View file

@ -27,6 +27,11 @@
#define PADDING_PIXELS 4
/*
* conferencee_box = a vbox where participants are added or removed
* conf_frame = the conference tab
*/
static GtkWidget *create_conference_label(void){
GtkWidget *box=gtk_hbox_new(FALSE,0);
gtk_box_pack_start(GTK_BOX(box),gtk_image_new_from_stock(GTK_STOCK_ADD,GTK_ICON_SIZE_MENU),FALSE,FALSE,0);
@ -46,34 +51,21 @@ static void init_local_participant(GtkWidget *participant){
linphone_gtk_init_audio_meter(sound_meter, (get_volume_t) linphone_core_get_conference_local_input_volume, linphone_gtk_get_core());
}
static GtkWidget *get_conference_tab(GtkWidget *mw){
GtkWidget *box=(GtkWidget*)g_object_get_data(G_OBJECT(mw),"conference_tab");
GtkWidget *conf_frame=(GtkWidget*)g_object_get_data(G_OBJECT(mw),"conf_frame");
if(conf_frame!=NULL){
if (box==NULL){
GtkWidget *conf_box=linphone_gtk_get_widget(conf_frame,"conf_box");
box=gtk_vbox_new(FALSE,0);
GtkWidget *participant=linphone_gtk_create_widget("main","callee_frame");
gtk_box_set_homogeneous(GTK_BOX(box),TRUE);
init_local_participant(participant);
gtk_box_pack_start(GTK_BOX(box),participant,FALSE,FALSE,PADDING_PIXELS);
gtk_widget_show(box);
g_object_set_data(G_OBJECT(mw),"conference_tab",box);
gtk_box_pack_start(GTK_BOX(conf_box),box,FALSE,FALSE,PADDING_PIXELS);
}
}
static GtkWidget *get_conferencee_box(GtkWidget *mw){
GtkWidget *box=(GtkWidget*)g_object_get_data(G_OBJECT(mw),"conferencee_box");
return box;
}
static GtkWidget *find_conferencee_from_call(LinphoneCall *call){
GtkWidget *mw=linphone_gtk_get_main_window();
get_conference_tab(mw);
GtkWidget *conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(mw),"conf_frame");
GtkWidget *conf_box=linphone_gtk_get_widget(conf_frame,"conf_box");
GtkWidget *conferencee_box=get_conferencee_box(mw);
GList *elem;
GtkWidget *ret=NULL;
if (conferencee_box==NULL) return NULL;
if (call!=NULL){
GList *l=gtk_container_get_children(GTK_CONTAINER(conf_box));
GList *l=gtk_container_get_children(GTK_CONTAINER(conferencee_box));
for(elem=l;elem!=NULL;elem=elem->next){
GtkWidget *frame=(GtkWidget*)elem->data;
if (call==g_object_get_data(G_OBJECT(frame),"call")){
@ -87,28 +79,53 @@ static GtkWidget *find_conferencee_from_call(LinphoneCall *call){
return ret;
}
static GtkWidget * create_conference_panel(void){
GtkWidget *mw=linphone_gtk_get_main_window();
GtkWidget *conf_frame=linphone_gtk_create_widget("main","conf_frame");
GtkWidget *conf_box=linphone_gtk_get_widget(conf_frame,"conf_box");
GtkWidget *button_conf=linphone_gtk_get_widget(conf_frame,"terminate_conf");
GtkWidget *image=create_pixmap("stopcall-small.png");
GtkWidget *box;
GtkWidget *viewswitch=linphone_gtk_get_widget(mw,"viewswitch");
gtk_button_set_image(GTK_BUTTON(button_conf),image);
g_signal_connect_swapped(G_OBJECT(button_conf),"clicked",(GCallback)linphone_gtk_terminate_call,NULL);
g_object_set_data(G_OBJECT(mw),"conf_frame",(gpointer)conf_frame);
box=gtk_vbox_new(FALSE,0);
GtkWidget *participant=linphone_gtk_create_widget("main","callee_frame");
gtk_widget_show(participant);
gtk_box_set_homogeneous(GTK_BOX(box),TRUE);
init_local_participant(participant);
gtk_box_pack_start(GTK_BOX(box),participant,FALSE,FALSE,PADDING_PIXELS);
gtk_widget_show(box);
g_object_set_data(G_OBJECT(mw),"conferencee_box",box);
gtk_box_pack_start(GTK_BOX(conf_box),box,FALSE,FALSE,PADDING_PIXELS);
gtk_notebook_append_page(GTK_NOTEBOOK(viewswitch),conf_frame,
create_conference_label());
return conf_frame;
}
void linphone_gtk_set_in_conference(LinphoneCall *call){
GtkWidget *mw=linphone_gtk_get_main_window();
GtkWidget *viewswitch=linphone_gtk_get_widget(mw,"viewswitch");
GtkWidget *conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(mw),"conf_frame");
g_object_set_data(G_OBJECT(mw),"is_conf",GINT_TO_POINTER(TRUE));
GtkWidget *viewswitch=linphone_gtk_get_widget(mw,"viewswitch");
if(conf_frame==NULL){
conf_frame=linphone_gtk_create_widget("main","conf_frame");
GtkWidget *button_conf=linphone_gtk_get_widget(conf_frame,"terminate_conf");
GtkWidget *image=create_pixmap("stopcall-small.png");
gtk_button_set_image(GTK_BUTTON(button_conf),image);
g_signal_connect_swapped(G_OBJECT(button_conf),"clicked",(GCallback)linphone_gtk_terminate_call,NULL);
g_object_set_data(G_OBJECT(mw),"conf_frame",(gpointer)conf_frame);
gtk_notebook_append_page(GTK_NOTEBOOK(viewswitch),conf_frame,
create_conference_label());
conf_frame=create_conference_panel();
}
GtkWidget *participant=find_conferencee_from_call(call);
GtkWidget *conf_box=linphone_gtk_get_widget(conf_frame,"conf_box");
GtkWidget *participant=find_conferencee_from_call(call);
if (participant==NULL){
const LinphoneAddress *addr=linphone_call_get_remote_address(call);
participant=linphone_gtk_create_widget("main","callee_frame");
/*create and add it */
GtkWidget *conferencee_box=get_conferencee_box(mw);
GtkWidget *sound_meter;
const LinphoneAddress *addr=linphone_call_get_remote_address(call);
gchar *markup;
participant=linphone_gtk_create_widget("main","callee_frame");
gtk_widget_show(participant);
if (linphone_address_get_display_name(addr)!=NULL){
markup=g_strdup_printf("<b>%s</b>",linphone_address_get_display_name(addr));
}else{
@ -119,11 +136,11 @@ void linphone_gtk_set_in_conference(LinphoneCall *call){
gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(participant,"callee_name_label")),markup);
g_free(markup);
sound_meter=linphone_gtk_get_widget(participant,"sound_indicator");
linphone_gtk_init_audio_meter(sound_meter, (get_volume_t) linphone_call_get_play_volume, call);
gtk_box_pack_start(GTK_BOX(conf_box),participant,FALSE,FALSE,PADDING_PIXELS);
linphone_gtk_init_audio_meter(sound_meter, (get_volume_t) linphone_call_get_play_volume, call);
gtk_box_pack_start(GTK_BOX(conferencee_box),participant,FALSE,FALSE,PADDING_PIXELS);
g_object_set_data_full(G_OBJECT(participant),"call",linphone_call_ref(call),(GDestroyNotify)linphone_call_unref);
gtk_notebook_set_current_page(GTK_NOTEBOOK(viewswitch),
gtk_notebook_page_num(GTK_NOTEBOOK(viewswitch),conf_frame));
gtk_notebook_page_num(GTK_NOTEBOOK(viewswitch),conf_frame));
}
}
@ -135,24 +152,26 @@ void linphone_gtk_terminate_conference_participant(LinphoneCall *call){
}
void linphone_gtk_unset_from_conference(LinphoneCall *call){
GtkWidget *mw=linphone_gtk_get_main_window();
GtkWidget *conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(mw),"conf_frame");
GtkWidget *conf_box=linphone_gtk_get_widget(conf_frame,"conf_box");
GtkWidget *frame;
if (conf_box==NULL) return; /*conference tab already destroyed*/
frame=find_conferencee_from_call(call);
GList *children;
GtkWidget *frame=find_conferencee_from_call(call);
if (frame){
GtkWidget *mw=linphone_gtk_get_main_window();
GtkWidget *conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(mw),"conf_frame");
GtkWidget *conferencee_box=g_object_get_data(G_OBJECT(mw),"conferencee_box");
GList *children;
g_message("Removing a participant from conference");
gtk_widget_destroy(frame);
children=gtk_container_get_children(GTK_CONTAINER(conferencee_box));
if (g_list_length(children)==1){ /* only local participant */
/*the conference is terminated */
g_message("The conference is terminated");
g_object_set_data(G_OBJECT(mw),"conferencee_box",NULL);
gtk_widget_destroy(conf_frame);
g_object_set_data(G_OBJECT(mw),"conf_frame",NULL);
}
g_list_free(children);
}
children=gtk_container_get_children(GTK_CONTAINER(conf_box));
if (g_list_length(children)==2){
/*the conference is terminated */
gtk_widget_destroy(conf_box);
g_object_set_data(G_OBJECT(mw),"conference_tab",NULL);
}
gtk_widget_destroy(conf_frame);
g_list_free(children);
g_object_set_data(G_OBJECT(mw),"is_conf",GINT_TO_POINTER(FALSE));
g_object_set_data(G_OBJECT(mw),"conf_frame",NULL);
}

View file

@ -5,7 +5,7 @@
<object class="GtkDialog" id="dscp_settings">
<property name="can_focus">False</property>
<property name="border_width">5</property>
<property name="title" translatable="yes">Dscp settings</property>
<property name="title" translatable="yes">DSCP settings</property>
<property name="modal">True</property>
<property name="type_hint">dialog</property>
<signal name="response" handler="linphone_gtk_dscp_edit_response" swapped="no"/>

View file

@ -32,7 +32,6 @@ enum{
FRIEND_ICON,
FRIEND_CALL,
FRIEND_CHAT,
FRIEND_CHAT_CONVERSATION,
FRIEND_LIST_NCOL
};
@ -76,17 +75,18 @@ static GdkPixbuf *create_call_picture(){
return pixbuf;
}
static GdkPixbuf *create_unread_msg(){
GdkPixbuf *pixbuf;
pixbuf = create_pixbuf("active_chat.png");
return pixbuf;
}
static GdkPixbuf *create_chat_picture(){
GdkPixbuf *pixbuf;
pixbuf = create_pixbuf("chat.png");
return pixbuf;
}
static GdkPixbuf *create_active_chat_picture(){
GdkPixbuf *pixbuf;
pixbuf = create_pixbuf("active_chat.png");
return pixbuf;
}
/*
void linphone_gtk_set_friend_status(GtkWidget *friendlist , LinphoneFriend * fid, const gchar *url, const gchar *status, const gchar *img){
GtkTreeIter iter;
@ -110,6 +110,16 @@ void linphone_gtk_set_friend_status(GtkWidget *friendlist , LinphoneFriend * fid
}
}
*/
gboolean linphone_gtk_friend_list_is_contact(const LinphoneAddress *addr){
LinphoneFriend *lf;
char *addr_str=linphone_address_as_string(addr);
lf=linphone_core_get_friend_by_address(linphone_gtk_get_core(),addr_str);
if(lf == NULL){
return FALSE;
} return TRUE;
}
static void linphone_gtk_set_selection_to_uri_bar(GtkTreeView *treeview){
GtkTreeSelection *select;
GtkTreeIter iter;
@ -156,11 +166,51 @@ void linphone_gtk_remove_contact(GtkWidget *button){
GtkTreeIter iter;
GtkTreeModel *model;
LinphoneFriend *lf=NULL;
LinphoneChatRoom *cr=NULL;
select = gtk_tree_view_get_selection(GTK_TREE_VIEW(linphone_gtk_get_widget(w,"contact_list")));
if (gtk_tree_selection_get_selected (select, &model, &iter))
{
gtk_tree_model_get (model, &iter,FRIEND_ID , &lf, -1);
linphone_core_remove_friend(linphone_gtk_get_core(),lf);
gtk_tree_model_get (model, &iter,FRIEND_CHATROOM , &cr, -1);
linphone_chat_room_delete_history(cr);
linphone_gtk_show_friends();
}
}
void linphone_gtk_delete_history(GtkWidget *button){
GtkWidget *w=linphone_gtk_get_main_window();
GtkTreeSelection *select;
GtkTreeIter iter;
GtkTreeModel *model;
GtkWidget *chat_view;
LinphoneFriend *lf=NULL;
GtkWidget *friendlist;
friendlist=linphone_gtk_get_widget(w,"contact_list");
chat_view=(GtkWidget *)g_object_get_data(G_OBJECT(friendlist),"chatview");
select = gtk_tree_view_get_selection(GTK_TREE_VIEW(friendlist));
if (gtk_tree_selection_get_selected (select, &model, &iter))
{
LinphoneChatRoom *cr;
gtk_tree_model_get (model, &iter,FRIEND_ID , &lf, -1);
gtk_tree_model_get (model, &iter,FRIEND_CHATROOM , &cr, -1);
linphone_chat_room_delete_history(cr);
if(chat_view!=NULL){
char *from=g_object_get_data(G_OBJECT(friendlist),"from");
char *addr=linphone_address_as_string(linphone_friend_get_address(lf));
if(g_strcmp0(from,addr)==0){
GtkTextView *text_view=GTK_TEXT_VIEW(linphone_gtk_get_widget(chat_view,"textview"));
GtkTextIter start;
GtkTextIter end;
GtkTextBuffer *text_buffer;
text_buffer=gtk_text_view_get_buffer(text_view);
gtk_text_buffer_get_bounds(text_buffer, &start, &end);
gtk_text_buffer_delete (text_buffer, &start, &end);
g_object_set_data(G_OBJECT(chat_view),"from_message",NULL);
}
}
linphone_gtk_show_friends();
}
}
@ -171,17 +221,21 @@ static void linphone_gtk_call_selected(GtkTreeView *treeview){
"start_call"));
}
void linphone_gtk_update_chat_picture(gboolean active){
void linphone_gtk_friend_list_update_chat_picture(){
GtkTreeIter iter;
GtkWidget *w = linphone_gtk_get_main_window();
GtkWidget *friendlist=linphone_gtk_get_widget(w,"contact_list");
GtkTreeModel *model=gtk_tree_view_get_model(GTK_TREE_VIEW(friendlist));
LinphoneChatRoom *cr=NULL;
int nbmsg=0;
if (gtk_tree_model_get_iter_first(model,&iter)) {
do{
if(!active){
gtk_list_store_set(GTK_LIST_STORE(model),&iter,FRIEND_CHAT,create_chat_picture(),-1);
gtk_tree_model_get (model, &iter,FRIEND_CHATROOM , &cr, -1);
nbmsg=linphone_chat_room_get_unread_messages_count(cr);
if(nbmsg != 0){
gtk_list_store_set(GTK_LIST_STORE(model),&iter,FRIEND_CHAT,create_unread_msg(),-1);
} else {
gtk_list_store_set(GTK_LIST_STORE(model),&iter,FRIEND_CHAT,create_active_chat_picture(),-1);
gtk_list_store_set(GTK_LIST_STORE(model),&iter,FRIEND_CHAT,create_chat_picture(),-1);
}
}while(gtk_tree_model_iter_next(model,&iter));
}
@ -192,6 +246,81 @@ static gboolean grab_focus(GtkWidget *w){
return FALSE;
}
void linphone_gtk_friend_list_set_chat_conversation(const LinphoneAddress *la){
GtkTreeIter iter;
GtkListStore *store=NULL;
GtkWidget *w = linphone_gtk_get_main_window();
GtkWidget *friendlist=linphone_gtk_get_widget(w,"contact_list");
GtkTreeModel *model=gtk_tree_view_get_model(GTK_TREE_VIEW(friendlist));
GtkWidget *chat_view=(GtkWidget*)g_object_get_data(G_OBJECT(friendlist),"chatview");
LinphoneFriend *lf=NULL;
LinphoneChatRoom *cr=NULL;
GtkNotebook *notebook=(GtkNotebook *)linphone_gtk_get_widget(w,"viewswitch");
char *la_str=linphone_address_as_string(la);
lf=linphone_core_get_friend_by_address(linphone_gtk_get_core(),la_str);
if(lf==NULL){
cr=linphone_gtk_create_chatroom(la);
g_object_set_data(G_OBJECT(friendlist),"from",la_str);
if(chat_view==NULL){
chat_view=linphone_gtk_init_chatroom(cr,la);
g_object_set_data(G_OBJECT(friendlist),"chatview",(gpointer)chat_view);
} else {
linphone_gtk_load_chatroom(cr,la,chat_view);
}
gtk_notebook_set_current_page(notebook,gtk_notebook_page_num(notebook,chat_view));
linphone_gtk_friend_list_update_chat_picture();
g_idle_add((GSourceFunc)grab_focus,linphone_gtk_get_widget(chat_view,"text_entry"));
} else {
store=GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(friendlist)));
if (gtk_tree_model_get_iter_first(model,&iter)) {
do{
const LinphoneAddress *uri;
char *lf_str;
gtk_tree_model_get(model, &iter,FRIEND_ID , &lf, -1);
uri=linphone_friend_get_address(lf);
lf_str=linphone_address_as_string(uri);
if( g_strcmp0(lf_str,la_str)==0){
gtk_tree_model_get (model, &iter,FRIEND_CHATROOM , &cr, -1);
if(cr==NULL){
cr=linphone_gtk_create_chatroom(uri);
gtk_list_store_set(store,&iter,FRIEND_CHATROOM,cr,-1);
}
g_object_set_data(G_OBJECT(friendlist),"from",linphone_address_as_string(uri));
if(chat_view==NULL){
chat_view=linphone_gtk_init_chatroom(cr,uri);
g_object_set_data(G_OBJECT(friendlist),"chatview",(gpointer)chat_view);
} else {
linphone_gtk_load_chatroom(cr,uri,chat_view);
}
gtk_notebook_set_current_page(notebook,gtk_notebook_page_num(notebook,chat_view));
linphone_gtk_friend_list_update_chat_picture();
g_idle_add((GSourceFunc)grab_focus,linphone_gtk_get_widget(chat_view,"text_entry"));
break;
}
}while(gtk_tree_model_iter_next(model,&iter));
}
}
}
void linphone_gtk_notebook_tab_select(GtkNotebook *notebook,GtkWidget *page,guint page_num, gpointer data){
GtkWidget *w=linphone_gtk_get_main_window();
GtkWidget *friendlist=linphone_gtk_get_widget(w,"contact_list");
GtkWidget *chat_view;
LinphoneChatRoom *cr=NULL;
chat_view=(GtkWidget*)g_object_get_data(G_OBJECT(friendlist),"chatview");
if(page != NULL){
notebook=(GtkNotebook *)linphone_gtk_get_widget(w,"viewswitch");
if(gtk_notebook_page_num(notebook,page)==gtk_notebook_page_num(notebook,chat_view)){
cr=g_object_get_data(G_OBJECT(chat_view),"cr");
if(cr!=NULL){
linphone_chat_room_mark_as_read(cr);
linphone_gtk_show_friends();
}
}
}
}
void linphone_gtk_chat_selected(GtkWidget *item){
GtkWidget *w=gtk_widget_get_toplevel(item);
GtkTreeSelection *select;
@ -209,21 +338,24 @@ void linphone_gtk_chat_selected(GtkWidget *item){
GtkNotebook *notebook=(GtkNotebook *)linphone_gtk_get_widget(w,"viewswitch");
const LinphoneAddress *uri;
gtk_tree_model_get (model, &iter,FRIEND_ID , &lf, -1);
gtk_tree_model_get (model, &iter,FRIEND_CHATROOM , &cr, -1);
uri=linphone_friend_get_address(lf);
if(cr == NULL){
if(cr==NULL){
cr=linphone_gtk_create_chatroom(uri);
gtk_list_store_set(store,&iter,FRIEND_CHATROOM,cr,-1);
}
page=(GtkWidget*)g_object_get_data(G_OBJECT(friendlist),"chatview");
g_object_set_data(G_OBJECT(friendlist),"from",linphone_address_as_string(uri));
if(page==NULL){
page=linphone_gtk_init_chatroom(cr,uri);
g_object_set_data(G_OBJECT(friendlist),"chatview",(gpointer)page);
} else {
linphone_gtk_load_chatroom(cr,uri,page);
}
linphone_chat_room_mark_as_read(cr);
gtk_notebook_set_current_page(notebook,gtk_notebook_page_num(notebook,page));
linphone_gtk_update_chat_picture(FALSE);
linphone_gtk_friend_list_update_chat_picture();
g_idle_add((GSourceFunc)grab_focus,linphone_gtk_get_widget(page,"text_entry"));
gtk_list_store_set(store,&iter,FRIEND_CHAT,create_active_chat_picture(),-1);
}
}
@ -382,7 +514,11 @@ static gboolean friend_search_func(GtkTreeModel *model, gint column,
gboolean ret=TRUE;
gtk_tree_model_get(model,iter,FRIEND_NAME,&name,-1);
if (name!=NULL){
ret=strstr(name,key)==NULL;
gchar *uname=g_utf8_casefold(name,-1); /* need that to perform case-insensitive search in utf8 */
gchar *ukey=g_utf8_casefold(key,-1);
ret=strstr(uname,ukey)==NULL;
g_free(uname);
g_free(ukey);
g_free(name);
}
return ret;
@ -421,6 +557,13 @@ static void on_name_column_clicked(GtkTreeModel *model){
static int get_friend_weight(const LinphoneFriend *lf){
int w=0;
LinphoneCore *lc=linphone_gtk_get_core();
LinphoneChatRoom *cr=linphone_core_get_chat_room(lc,linphone_friend_get_address(lf));
if (cr && linphone_chat_room_get_unread_messages_count(cr)>0){
w+=2000;
}
switch(linphone_friend_get_status(lf)){
case LinphoneStatusOnline:
w+=1000;
@ -496,7 +639,7 @@ static void linphone_gtk_friend_list_init(GtkWidget *friendlist){
linphone_gtk_init_bookmark_icon();
store = gtk_list_store_new(FRIEND_LIST_NCOL,GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER,
G_TYPE_POINTER, G_TYPE_STRING, GDK_TYPE_PIXBUF, GDK_TYPE_PIXBUF, GDK_TYPE_PIXBUF, G_TYPE_STRING);
G_TYPE_POINTER, G_TYPE_STRING, GDK_TYPE_PIXBUF, GDK_TYPE_PIXBUF, GDK_TYPE_PIXBUF);
gtk_tree_view_set_model(GTK_TREE_VIEW(friendlist),GTK_TREE_MODEL(store));
g_object_unref(G_OBJECT(store));
@ -506,7 +649,7 @@ static void linphone_gtk_friend_list_init(GtkWidget *friendlist){
gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(friendlist),friend_search_func,NULL,NULL);
gtk_tree_view_set_search_column(GTK_TREE_VIEW(friendlist),FRIEND_NAME);
gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store),FRIEND_NAME,friend_sort,NULL,NULL);
/*Name and presence column*/
renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes (_("Presence status"),
@ -517,6 +660,7 @@ static void linphone_gtk_friend_list_init(GtkWidget *friendlist){
g_signal_connect_swapped(G_OBJECT(column),"clicked",(GCallback)on_presence_column_clicked,GTK_TREE_MODEL(store));
gtk_tree_view_column_set_clickable(column,TRUE);
gtk_tree_view_column_set_visible(column,linphone_gtk_get_ui_config_int("friendlist_status",1));
gtk_tree_view_column_set_min_width(column,50);
renderer = gtk_cell_renderer_pixbuf_new();
gtk_tree_view_column_pack_start(column,renderer,TRUE);
@ -541,7 +685,7 @@ static void linphone_gtk_friend_list_init(GtkWidget *friendlist){
column = gtk_tree_view_column_new_with_attributes (_("Call"),renderer,"pixbuf",FRIEND_CALL,NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (friendlist), column);
/* chat column*/
/* Chat column*/
renderer = gtk_cell_renderer_pixbuf_new();
column = gtk_tree_view_column_new_with_attributes (_("Chat"),renderer,"pixbuf",FRIEND_CHAT,NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (friendlist), column);
@ -554,7 +698,7 @@ static void linphone_gtk_friend_list_init(GtkWidget *friendlist){
gtk_tree_view_set_tooltip_column(GTK_TREE_VIEW(friendlist),FRIEND_SIP_ADDRESS);
#endif
gtk_widget_set_size_request(friendlist,200,100);
gtk_widget_set_size_request(friendlist,200,120);
/*gtk_combo_box_set_active(GTK_COMBO_BOX(linphone_gtk_get_widget(
gtk_widget_get_toplevel(friendlist),"show_category")),0);*/
}
@ -623,9 +767,9 @@ void linphone_gtk_show_friends(void){
//const gchar *search=NULL;
//gboolean lookup=FALSE;
MSList *sorted;
LinphoneChatRoom *cr=NULL;
linphone_gtk_show_directory_search();
if (gtk_tree_view_get_model(GTK_TREE_VIEW(friendlist))==NULL){
linphone_gtk_friend_list_init(friendlist);
}
@ -647,6 +791,9 @@ void linphone_gtk_show_friends(void){
const char *name=linphone_address_get_display_name(f_uri);
const char *display=name;
char *escaped=NULL;
//char buf[26]={0};
int nbmsg=0;
/*if (lookup){
if (strstr(uri,search)==NULL){
ms_free(uri);
@ -661,11 +808,13 @@ void linphone_gtk_show_friends(void){
gtk_list_store_append(store,&iter);
gtk_list_store_set(store,&iter,FRIEND_NAME, display,FRIEND_ID,lf,
FRIEND_PRESENCE_IMG, send_subscribe ? create_status_picture(linphone_friend_get_status(lf)) : NULL,
-1);
gtk_list_store_set(store,&iter,FRIEND_CALL,create_call_picture(),-1);
gtk_list_store_set(store,&iter,FRIEND_CHAT,create_chat_picture(),-1);
FRIEND_CHAT,create_chat_picture(),FRIEND_CALL,create_call_picture(),-1);
cr=linphone_gtk_create_chatroom(f_uri);
gtk_list_store_set(store,&iter,FRIEND_CHATROOM,cr,-1);
nbmsg=linphone_chat_room_get_unread_messages_count(cr);
if(nbmsg != 0){
gtk_list_store_set(store,&iter,FRIEND_CHAT,create_unread_msg(),-1);
}
escaped=g_markup_escape_text(uri,-1);
gtk_list_store_set(store,&iter,FRIEND_SIP_ADDRESS,escaped,-1);
g_free(escaped);
@ -712,9 +861,11 @@ void linphone_gtk_contact_cancel(GtkWidget *button){
void linphone_gtk_contact_ok(GtkWidget *button){
GtkWidget *w=gtk_widget_get_toplevel(button);
LinphoneFriend *lf=(LinphoneFriend*)g_object_get_data(G_OBJECT(w),"friend_ref");
LinphoneFriend *lf2;
char *fixed_uri=NULL;
gboolean show_presence=FALSE,allow_presence=FALSE;
const gchar *name,*uri;
LinphoneAddress* friend_address;
if (lf==NULL){
lf=linphone_friend_new();
if (linphone_gtk_get_ui_config_int("use_subscribe_notify",1)==1){
@ -733,19 +884,23 @@ void linphone_gtk_contact_ok(GtkWidget *button){
linphone_gtk_display_something(GTK_MESSAGE_WARNING,_("Invalid sip contact !"));
return ;
}
LinphoneAddress* friend_address = linphone_address_new(fixed_uri);
friend_address = linphone_address_new(fixed_uri);
linphone_address_set_display_name(friend_address,name);
linphone_friend_set_addr(lf,friend_address);
ms_free(fixed_uri);
linphone_address_destroy(friend_address);
linphone_friend_send_subscribe(lf,show_presence);
linphone_friend_set_inc_subscribe_policy(lf,allow_presence==TRUE ? LinphoneSPAccept : LinphoneSPDeny);
if (linphone_friend_in_list(lf)) {
linphone_friend_done(lf);
}else{
linphone_core_add_friend(linphone_gtk_get_core(),lf);
} else {
lf2=linphone_core_get_friend_by_address(linphone_gtk_get_core(),fixed_uri);
if(lf2==NULL){
linphone_friend_set_name(lf,name);
linphone_core_add_friend(linphone_gtk_get_core(),lf);
}
}
ms_free(fixed_uri);
linphone_gtk_show_friends();
gtk_widget_destroy(w);
}
@ -757,6 +912,7 @@ static GtkWidget *linphone_gtk_create_contact_menu(GtkWidget *contact_list){
gchar *text_label=NULL;
gchar *edit_label=NULL;
gchar *delete_label=NULL;
gchar *delete_hist_label=NULL;
gchar *name=NULL;
GtkTreeSelection *select;
GtkTreeIter iter;
@ -779,6 +935,7 @@ static GtkWidget *linphone_gtk_create_contact_menu(GtkWidget *contact_list){
text_label=g_strdup_printf(_("Send text to %s"),name);
edit_label=g_strdup_printf(_("Edit contact '%s'"),name);
delete_label=g_strdup_printf(_("Delete contact '%s'"),name);
delete_hist_label=g_strdup_printf(_("Delete chat history of '%s'"),name);
g_free(name);
}
if (call_label){
@ -818,6 +975,15 @@ static GtkWidget *linphone_gtk_create_contact_menu(GtkWidget *contact_list){
g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_remove_contact,contact_list);
}
if (delete_hist_label){
menu_item=gtk_image_menu_item_new_with_label(delete_hist_label);
image=gtk_image_new_from_stock(GTK_STOCK_CLEAR,GTK_ICON_SIZE_MENU);
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),image);
gtk_widget_show(image);
gtk_widget_show(menu_item);
gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item);
g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_delete_history,contact_list);
}
if (ssc && (sip_setup_context_get_capabilities(ssc) & SIP_SETUP_CAP_BUDDY_LOOKUP)) {
gchar *tmp=g_strdup_printf(_("Add new contact from %s directory"),linphone_proxy_config_get_domain(cfg));
@ -854,52 +1020,41 @@ gboolean linphone_gtk_popup_contact_menu(GtkWidget *list, GdkEventButton *event)
}
gint get_col_number_from_tree_view_column (GtkTreeViewColumn *col){
GList *cols;
gint num;
g_return_val_if_fail ( col != NULL, -1 );
g_return_val_if_fail ( col->tree_view != NULL, -1 );
cols = gtk_tree_view_get_columns(GTK_TREE_VIEW(col->tree_view));
num = g_list_index(cols, (gpointer) col);
g_list_free(cols);
GList *cols;
gint num;
g_return_val_if_fail ( col != NULL, -1 );
g_return_val_if_fail ( col->tree_view != NULL, -1 );
cols = gtk_tree_view_get_columns(GTK_TREE_VIEW(col->tree_view));
num = g_list_index(cols, (gpointer) col);
g_list_free(cols);
return num;
}
int longueur_list (GtkTreeView *tree_view){
GtkTreeIter iter;
int i=0;
GtkTreeModel *model=gtk_tree_view_get_model(tree_view);
if (gtk_tree_model_get_iter_first(model,&iter)) {
do{
i++;
}while(gtk_tree_model_iter_next(model,&iter));
}
return i;
return num;
}
static gint tree_view_get_cell_from_pos(GtkTreeView *view, guint x, guint y){
GtkTreeViewColumn *col = NULL;
GList *node, *columns;
gint colx = 0;
gint coly = longueur_list(view);
gint height=0;
GtkTreePath *path;
GtkTreeViewDropPosition pos;
g_return_val_if_fail ( view != NULL, 0 );
columns = gtk_tree_view_get_columns(view);
for (node = columns; node != NULL && col == NULL; node = node->next){
GtkTreeViewColumn *checkcol = (GtkTreeViewColumn*) node->data;
gtk_tree_view_column_cell_get_size(checkcol,NULL,NULL,NULL,NULL,&height);
if (x >= colx && x < (colx + checkcol->width) && y < height*coly){
col = checkcol;
gint num = get_col_number_from_tree_view_column(col);
gtk_tree_view_get_dest_row_at_pos(view,x,y,&path,&pos);
if(path != NULL){
for (node = columns; node != NULL && col == NULL; node = node->next){
GtkTreeViewColumn *checkcol = (GtkTreeViewColumn*) node->data;
if (x >= colx && x < (colx + checkcol->width)){
col = checkcol;
gint num = get_col_number_from_tree_view_column(col);
return num;
}
else {
colx += checkcol->width;
} else {
colx += checkcol->width;
}
}
g_list_free(columns);
}
}
g_list_free(columns);
return 0;
}
@ -922,6 +1077,4 @@ gboolean linphone_gtk_contact_list_button_pressed(GtkWidget *widget, GdkEventBut
void linphone_gtk_buddy_info_updated(LinphoneCore *lc, LinphoneFriend *lf){
/*refresh the entire list*/
linphone_gtk_show_friends();
}
}

View file

@ -50,7 +50,8 @@ LinphoneCall *linphone_gtk_get_currently_displayed_call(gboolean *is_conf){
if (page!=NULL){
LinphoneCall *call=(LinphoneCall*)g_object_get_data(G_OBJECT(page),"call");
if (call==NULL){
if (GPOINTER_TO_INT(g_object_get_data(G_OBJECT(main_window),"is_conf"))){
GtkWidget *conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(main_window),"conf_frame");
if (conf_frame==page){
if (is_conf)
*is_conf=TRUE;
return NULL;
@ -74,26 +75,29 @@ static GtkWidget *make_tab_header(int number){
return w;
}
void update_tab_header(LinphoneCall *call,gboolean pause){
GtkWidget *w=(GtkWidget*)linphone_call_get_user_pointer(call);
GtkWidget *main_window=linphone_gtk_get_main_window();
GtkNotebook *notebook=GTK_NOTEBOOK(linphone_gtk_get_widget(main_window,"viewswitch"));
gint call_index=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"call_index"));
GtkWidget *new_label=gtk_hbox_new (FALSE,0);
GtkWidget *i=NULL;
if(pause){
i=gtk_image_new_from_stock(GTK_STOCK_MEDIA_PAUSE,GTK_ICON_SIZE_SMALL_TOOLBAR);
} else {
i=create_pixmap ("startcall-small.png");
}
void linphone_gtk_call_update_tab_header(LinphoneCall *call,gboolean pause){
GtkWidget *w=(GtkWidget*)linphone_call_get_user_pointer(call);
GtkWidget *main_window=linphone_gtk_get_main_window();
GtkNotebook *notebook=GTK_NOTEBOOK(linphone_gtk_get_widget(main_window,"viewswitch"));
gint call_index=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"call_index"));
GtkWidget *new_label=gtk_hbox_new (FALSE,0);
GtkWidget *i=NULL;
GtkWidget *l;
gchar *text=g_strdup_printf(_("Call #%i"),call_index);
gchar *text;
if(pause){
i=gtk_image_new_from_stock(GTK_STOCK_MEDIA_PAUSE,GTK_ICON_SIZE_SMALL_TOOLBAR);
} else {
i=create_pixmap ("startcall-small.png");
}
text=g_strdup_printf(_("Call #%i"),call_index);
l=gtk_label_new (text);
gtk_box_pack_start (GTK_BOX(new_label),i,FALSE,FALSE,0);
gtk_box_pack_end(GTK_BOX(new_label),l,TRUE,TRUE,0);
gtk_notebook_set_tab_label(notebook,w,new_label);
gtk_widget_show_all(new_label);
gtk_notebook_set_tab_label(notebook,w,new_label);
gtk_widget_show_all(new_label);
}
static void linphone_gtk_in_call_set_animation_image(GtkWidget *callview, const char *image_name, gboolean is_stock){
@ -101,7 +105,7 @@ static void linphone_gtk_in_call_set_animation_image(GtkWidget *callview, const
GList *elem=gtk_container_get_children(GTK_CONTAINER(container));
GtkWidget *image;
if (!is_stock){
if (!is_stock){
if (image_name==NULL){
gtk_widget_hide(container);
}
@ -157,8 +161,7 @@ void transfer_button_clicked(GtkWidget *button, gpointer call_ref){
g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_transfer_call,other_call);
}
}
gtk_menu_popup(GTK_MENU(menu),NULL,NULL,NULL,NULL,0,
gtk_get_current_event_time());
gtk_menu_popup(GTK_MENU(menu),NULL,NULL,NULL,NULL,0,gtk_get_current_event_time());
gtk_widget_show(menu);
}
@ -178,7 +181,6 @@ static void conference_button_clicked(GtkWidget *button, gpointer call_ref){
gtk_widget_set_sensitive(button,FALSE);
g_object_set_data(G_OBJECT(linphone_gtk_get_main_window()),"conf_frame",NULL);
linphone_core_add_all_to_conference(linphone_gtk_get_core());
//linphone_core_add_to_conference(linphone_gtk_get_core(),(LinphoneCall*)call_ref);
}
@ -202,7 +204,6 @@ static void show_used_codecs(GtkWidget *callstats, LinphoneCall *call){
GtkWidget *acodec_ui=linphone_gtk_get_widget(callstats,"audio_codec");
GtkWidget *vcodec_ui=linphone_gtk_get_widget(callstats,"video_codec");
if (acodec){
char tmp[64]={0};
snprintf(tmp,sizeof(tmp)-1,"%s/%i/%i",acodec->mime_type,acodec->clock_rate,acodec->channels);
gtk_label_set_label(GTK_LABEL(acodec_ui),tmp);
@ -231,19 +232,61 @@ static const char *ice_state_to_string(LinphoneIceState ice_state){
return "invalid";
}
static const char *upnp_state_to_string(LinphoneUpnpState ice_state){
switch(ice_state){
case LinphoneUpnpStateIdle:
return _("uPnP not activated");
case LinphoneUpnpStatePending:
return _("uPnP in progress");
case LinphoneUpnpStateNotAvailable:
return _("uPnp not available");
case LinphoneUpnpStateOk:
return _("uPnP is running");
case LinphoneUpnpStateKo:
return _("uPnP failed");
default:
break;
}
return "invalid";
}
static void _refresh_call_stats(GtkWidget *callstats, LinphoneCall *call){
const LinphoneCallStats *as=linphone_call_get_audio_stats(call);
const LinphoneCallStats *vs=linphone_call_get_video_stats(call);
LinphoneIceState ice_state=as->ice_state;
const char *audio_media_connectivity = _("Direct or through server");
const char *video_media_connectivity = _("Direct or through server");
gboolean has_video=linphone_call_params_video_enabled(linphone_call_get_current_params(call));
gchar *tmp=g_strdup_printf(_("download: %f\nupload: %f (kbit/s)"),
as->download_bandwidth,as->upload_bandwidth);
gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(callstats,"audio_bandwidth_usage")),tmp);
g_free(tmp);
tmp=g_strdup_printf(_("download: %f\nupload: %f (kbit/s)"),
vs->download_bandwidth,vs->upload_bandwidth);
if (has_video)
tmp=g_strdup_printf(_("download: %f\nupload: %f (kbit/s)"),vs->download_bandwidth,vs->upload_bandwidth);
else tmp=NULL;
gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(callstats,"video_bandwidth_usage")),tmp);
g_free(tmp);
gtk_label_set_text(GTK_LABEL(linphone_gtk_get_widget(callstats,"media_connectivity")),ice_state_to_string(ice_state));
if (tmp) g_free(tmp);
if(as->upnp_state != LinphoneUpnpStateNotAvailable && as->upnp_state != LinphoneUpnpStateIdle) {
audio_media_connectivity = upnp_state_to_string(as->upnp_state);
} else if(as->ice_state != LinphoneIceStateNotActivated) {
audio_media_connectivity = ice_state_to_string(as->ice_state);
}
gtk_label_set_text(GTK_LABEL(linphone_gtk_get_widget(callstats,"audio_media_connectivity")),audio_media_connectivity);
if (has_video){
if(vs->upnp_state != LinphoneUpnpStateNotAvailable && vs->upnp_state != LinphoneUpnpStateIdle) {
video_media_connectivity = upnp_state_to_string(vs->upnp_state);
} else if(vs->ice_state != LinphoneIceStateNotActivated) {
video_media_connectivity = ice_state_to_string(vs->ice_state);
}
}else video_media_connectivity=NULL;
gtk_label_set_text(GTK_LABEL(linphone_gtk_get_widget(callstats,"video_media_connectivity")),video_media_connectivity);
if (as->round_trip_delay>0){
tmp=g_strdup_printf(_("%.3f seconds"),as->round_trip_delay);
gtk_label_set_text(GTK_LABEL(linphone_gtk_get_widget(callstats,"round_trip_time")),tmp);
g_free(tmp);
}
}
static gboolean refresh_call_stats(GtkWidget *callstats){
@ -388,8 +431,6 @@ void linphone_gtk_remove_in_call_view(LinphoneCall *call){
int idx;
g_return_if_fail(w!=NULL);
idx=gtk_notebook_page_num(GTK_NOTEBOOK(nb),w);
gtk_notebook_remove_page (GTK_NOTEBOOK(nb),idx);
gtk_widget_destroy(w);
if (in_conf){
linphone_gtk_unset_from_conference(call);
}
@ -401,12 +442,13 @@ void linphone_gtk_remove_in_call_view(LinphoneCall *call){
/*show the conference*/
gtk_notebook_set_current_page(GTK_NOTEBOOK(nb),gtk_notebook_page_num(GTK_NOTEBOOK(nb),
g_object_get_data(G_OBJECT(main_window),"conf_frame")));
}else gtk_notebook_set_current_page(GTK_NOTEBOOK(nb), 0);
}else gtk_notebook_prev_page(GTK_NOTEBOOK(nb));
}else{
/*show the active call*/
gtk_notebook_set_current_page(GTK_NOTEBOOK(nb),gtk_notebook_page_num(GTK_NOTEBOOK(nb),
linphone_call_get_user_pointer(call)));
gtk_notebook_set_current_page(GTK_NOTEBOOK(nb),gtk_notebook_page_num(GTK_NOTEBOOK(nb), linphone_call_get_user_pointer(call)));
}
gtk_notebook_remove_page (GTK_NOTEBOOK(nb),idx);
gtk_widget_destroy(w);
}
static void display_peer_name_in_label(GtkWidget *label, const LinphoneAddress *from){
@ -637,18 +679,16 @@ void linphone_gtk_in_call_view_set_in_call(LinphoneCall *call){
GtkWidget *call_stats=(GtkWidget*)g_object_get_data(G_OBJECT(callview),"call_stats");
display_peer_name_in_label(callee,linphone_call_get_remote_address (call));
gtk_widget_set_visible(linphone_gtk_get_widget(callview,"buttons_panel"),!in_conf);
gtk_widget_hide(linphone_gtk_get_widget(callview,"answer_decline_panel"));
gtk_label_set_markup(GTK_LABEL(status),in_conf ? _("In conference") : _("<b>In call</b>"));
gtk_widget_set_sensitive(linphone_gtk_get_widget(callview,"conference_button"),!in_conf);
gtk_widget_set_sensitive(linphone_gtk_get_widget(callview,"transfer_button"),!in_conf);
gtk_label_set_text(GTK_LABEL(duration),_("00::00::00"));
linphone_gtk_in_call_set_animation_image(callview,GTK_STOCK_MEDIA_PLAY,TRUE);
update_tab_header(call,FALSE);
linphone_gtk_call_update_tab_header(call,FALSE);
linphone_gtk_enable_mute_button(
GTK_BUTTON(linphone_gtk_get_widget(callview,"incall_mute")),TRUE);
@ -661,8 +701,15 @@ void linphone_gtk_in_call_view_set_in_call(LinphoneCall *call){
if (in_conf){
linphone_gtk_set_in_conference(call);
gtk_widget_set_sensitive(linphone_gtk_get_widget(callview,"incall_mute"),FALSE);
gtk_widget_set_sensitive(linphone_gtk_get_widget(callview,"hold_call"),FALSE);
}else{
linphone_gtk_unset_from_conference(call); /*in case it was previously*/
gtk_widget_set_sensitive(linphone_gtk_get_widget(callview,"incall_mute"),TRUE);
gtk_widget_set_sensitive(linphone_gtk_get_widget(callview,"hold_call"),TRUE);
}
gtk_widget_show_all(linphone_gtk_get_widget(callview,"buttons_panel"));
if (!in_conf) gtk_widget_show_all(linphone_gtk_get_widget(callview,"record_hbox"));
else gtk_widget_hide(linphone_gtk_get_widget(callview,"record_hbox"));
if (call_stats) show_used_codecs(call_stats,call);
}
@ -694,11 +741,12 @@ static gboolean in_call_view_terminated(LinphoneCall *call){
void linphone_gtk_in_call_view_terminate(LinphoneCall *call, const char *error_msg){
GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call);
if(callview==NULL) return;
GtkWidget *status=linphone_gtk_get_widget(callview,"in_call_status");
guint taskid=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(callview),"taskid"));
gboolean in_conf=linphone_call_params_local_conference_mode(linphone_call_get_current_params(call));
if ((callview==NULL) || (status==NULL)) return;
if (status==NULL) return;
if (error_msg==NULL)
gtk_label_set_markup(GTK_LABEL(status),_("<b>Call ended.</b>"));
else{
@ -710,15 +758,14 @@ void linphone_gtk_in_call_view_terminate(LinphoneCall *call, const char *error_m
linphone_gtk_get_ui_config("stop_call_icon","stopcall-red.png"),FALSE);
gtk_widget_hide(linphone_gtk_get_widget(callview,"answer_decline_panel"));
gtk_widget_hide(linphone_gtk_get_widget(callview,"record_hbox"));
gtk_widget_hide(linphone_gtk_get_widget(callview,"buttons_panel"));
gtk_widget_hide(linphone_gtk_get_widget(callview,"incall_audioview"));
gtk_widget_hide(linphone_gtk_get_widget(callview,"terminate_call"));
gtk_widget_hide(linphone_gtk_get_widget(callview,"video_button"));
gtk_widget_hide(linphone_gtk_get_widget(callview,"transfer_button"));
gtk_widget_hide(linphone_gtk_get_widget(callview,"conference_button"));
gtk_widget_hide(linphone_gtk_get_widget(callview,"quality_indicator"));
linphone_gtk_enable_mute_button(
GTK_BUTTON(linphone_gtk_get_widget(callview,"incall_mute")),FALSE);
linphone_gtk_enable_hold_button(call,FALSE,TRUE);
if (taskid!=0) g_source_remove(taskid);
g_timeout_add_seconds(2,(GSourceFunc)in_call_view_terminated,call);
if (in_conf)
@ -800,7 +847,7 @@ void linphone_gtk_draw_hold_button(GtkButton *button, gboolean active){
void linphone_gtk_hold_clicked(GtkButton *button){
int active=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(button),"active"));
LinphoneCall *call=linphone_gtk_get_currently_displayed_call(NULL);
update_tab_header(call,active);
linphone_gtk_call_update_tab_header(call,active);
if (!call) return;
if(!active)
{
@ -816,7 +863,7 @@ void linphone_gtk_enable_hold_button(LinphoneCall *call, gboolean sensitive, gbo
GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer (call);
GtkWidget *button;
g_return_if_fail(callview!=NULL);
update_tab_header(call,!holdon);
linphone_gtk_call_update_tab_header(call,!holdon);
button=linphone_gtk_get_widget(callview,"hold_call");
gtk_widget_set_sensitive(GTK_WIDGET(button),sensitive);
gtk_widget_set_visible(GTK_WIDGET(button),sensitive);
@ -827,3 +874,48 @@ void linphone_gtk_call_statistics_closed(GtkWidget *call_stats){
gtk_widget_destroy(call_stats);
}
void linphone_gtk_record_call_toggled(GtkWidget *button){
gboolean active=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
gboolean is_conf=FALSE;
const char *filepath;
gchar *message;
LinphoneCore *lc=linphone_gtk_get_core();
LinphoneCall *call=linphone_gtk_get_currently_displayed_call(&is_conf);
GtkWidget *callview;
GtkWidget *label;
if (call){
callview=(GtkWidget*)linphone_call_get_user_pointer (call);
const LinphoneCallParams *params=linphone_call_get_current_params(call);
filepath=linphone_call_params_get_record_file(params);
label=linphone_gtk_get_widget(callview,"record_status");
}else if (is_conf){
GtkWidget *mw=linphone_gtk_get_main_window();
callview=(GtkWidget *)g_object_get_data(G_OBJECT(linphone_gtk_get_main_window()),"conf_frame");
label=linphone_gtk_get_widget(callview,"conf_record_status");
filepath=(const char*)g_object_get_data(G_OBJECT(mw),"conf_record_path");
if (filepath==NULL){
filepath=linphone_gtk_get_record_path(NULL,TRUE);
g_object_set_data_full(G_OBJECT(mw),"conf_record_path",(char*)filepath,g_free);
}
}else{
g_warning("linphone_gtk_record_call_toggled(): bug.");
return;
}
message=g_strdup_printf(_("<small><i>Recording into\n%s %s</i></small>"),filepath,active ? "" : _("(Paused)"));
if (active){
if (call)
linphone_call_start_recording(call);
else
linphone_core_start_conference_recording(lc,filepath);
}else {
if (call)
linphone_call_stop_recording(call);
else
linphone_core_stop_conference_recording(lc);
}
gtk_label_set_markup(GTK_LABEL(label),message);
g_free(message);
}

277
gtk/keypad.ui Normal file
View file

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

View file

@ -58,6 +58,7 @@ GtkWidget *linphone_gtk_create_window(const char *window_name);
GtkWidget *linphone_gtk_get_widget(GtkWidget *window, const char *name);
GtkWidget *linphone_gtk_create_widget(const char *filename, const char *widget_name);
const char *linphone_gtk_message_storage_get_db_file(const char *filename);
void linphone_gtk_show_assistant(void);
void linphone_gtk_close_assistant(void);
@ -66,15 +67,11 @@ GtkWidget *linphone_gtk_get_main_window();
void linphone_gtk_display_something(GtkMessageType type,const gchar *message);
void linphone_gtk_start_call(GtkWidget *button);
void linphone_gtk_call_terminated();
void linphone_gtk_show_friends(void);
void linphone_gtk_show_contact(LinphoneFriend *lf);
void linphone_gtk_set_my_presence(LinphoneOnlineStatus ss);
void linphone_gtk_show_parameters(void);
void linphone_gtk_fill_soundcards(GtkWidget *pb);
void linphone_gtk_fill_webcams(GtkWidget *pb);
void linphone_gtk_load_identities(void);
LinphoneChatRoom * linphone_gtk_create_chatroom(const LinphoneAddress *with);
void linphone_gtk_text_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddress *from, const char *message);
void linphone_gtk_call_log_update(GtkWidget *w);
void linphone_gtk_create_log_window(void);
void linphone_gtk_log_show(void);
@ -83,7 +80,6 @@ void linphone_gtk_log_push(OrtpLogLevel lev, const char *fmt, va_list args);
void linphone_gtk_destroy_log_window(void);
void linphone_gtk_refer_received(LinphoneCore *lc, const char *refer_to);
gboolean linphone_gtk_check_logs();
void linphone_gtk_buddy_info_updated(LinphoneCore *lc, LinphoneFriend *lf);
const gchar *linphone_gtk_get_ui_config(const char *key, const char *def);
int linphone_gtk_get_ui_config_int(const char *key, int def);
void linphone_gtk_set_ui_config_int(const char *key , int val);
@ -97,21 +93,25 @@ SipSetupContext* linphone_gtk_get_default_sip_setup_context(void);
GtkWidget * linphone_gtk_show_buddy_lookup_window(SipSetupContext *ctx);
void linphone_gtk_buddy_lookup_set_keyword(GtkWidget *w, const char *kw);
void * linphone_gtk_wait(LinphoneCore *lc, void *ctx, LinphoneWaitingState ws, const char *purpose, float progress);
void linphone_gtk_terminate_call(GtkWidget *button);
void update_tab_header(LinphoneCall *call,gboolean pause);
void linphone_gtk_call_update_tab_header(LinphoneCall *call,gboolean pause);
void linphone_gtk_show_directory_search(void);
void linphone_gtk_status_icon_set_blinking(gboolean val);
void linphone_gtk_notify(LinphoneCall *call, const char *msg);
LinphoneChatRoom *linphone_gtk_start_chat(GtkTreeView* t);
void linphone_gtk_load_chatroom(LinphoneChatRoom *cr,const LinphoneAddress *uri,GtkWidget *chat_view);
void linphone_gtk_send_text();
GtkWidget * linphone_gtk_init_chatroom(LinphoneChatRoom *cr, const LinphoneAddress *with);
void linphone_gtk_update_chat_picture(gboolean active);
void linphone_gtk_chat_set_conversation(const LinphoneAddress *uri,gchar *conversation);
gchar * linphone_gtk_chat_get_conversation(const LinphoneAddress *uri);
LinphoneChatRoom * linphone_gtk_create_chatroom(const LinphoneAddress *with);
void linphone_gtk_text_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *msg);
void linphone_gtk_friend_list_update_chat_picture();
void linphone_gtk_friend_list_set_chat_conversation(const LinphoneAddress *la);
gboolean linphone_gtk_friend_list_is_contact(const LinphoneAddress *addr);
void linphone_gtk_notebook_tab_select(GtkNotebook *notebook,GtkWidget *page,guint page_num, gpointer data);
void linphone_gtk_show_friends(void);
void linphone_gtk_show_contact(LinphoneFriend *lf);
void linphone_gtk_buddy_info_updated(LinphoneCore *lc, LinphoneFriend *lf);
/*functions controlling the different views*/
gboolean linphone_gtk_use_in_call_view();
@ -149,3 +149,4 @@ void linphone_gtk_uninit_instance(void);
void linphone_gtk_monitor_usb(void);
void linphone_gtk_unmonitor_usb(void);
gchar *linphone_gtk_get_record_path(const LinphoneAddress *address, gboolean is_conference);

View file

@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include <sys/stat.h>
#include <sys/types.h>
#endif
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
extern gchar *linphone_logfile;

View file

@ -63,12 +63,16 @@ static void linphone_gtk_call_log_updated(LinphoneCore *lc, LinphoneCallLog *cl)
static void linphone_gtk_call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cs, const char *msg);
static void linphone_gtk_call_encryption_changed(LinphoneCore *lc, LinphoneCall *call, bool_t enabled, const char *token);
static void linphone_gtk_transfer_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate);
void linphone_gtk_save_main_window_position(GtkWindow* mw, GdkEvent *event, gpointer data);
static gboolean linphone_gtk_auto_answer(LinphoneCall *call);
void linphone_gtk_status_icon_set_blinking(gboolean val);
void _linphone_gtk_enable_video(gboolean val);
#ifndef HAVE_GTK_OSX
static gint main_window_x=0;
static gint main_window_y=0;
#endif
static gboolean verbose=0;
static gboolean auto_answer = 0;
static gchar * addr_to_call = NULL;
@ -216,7 +220,7 @@ static const char *linphone_gtk_get_factory_config_file(){
}
static void linphone_gtk_init_liblinphone(const char *config_file,
const char *factory_config_file) {
const char *factory_config_file, const char *db_file) {
LinphoneCoreVTable vtable={0};
gchar *secrets_file=linphone_gtk_get_config_file(SECRETS_FILE);
@ -230,7 +234,8 @@ static void linphone_gtk_init_liblinphone(const char *config_file,
vtable.display_warning=linphone_gtk_display_warning;
vtable.display_url=linphone_gtk_display_url;
vtable.call_log_updated=linphone_gtk_call_log_updated;
vtable.text_received=linphone_gtk_text_received;
//vtable.text_received=linphone_gtk_text_received;
vtable.message_received=linphone_gtk_text_received;
vtable.refer_received=linphone_gtk_refer_received;
vtable.buddy_info_updated=linphone_gtk_buddy_info_updated;
vtable.call_encryption_changed=linphone_gtk_call_encryption_changed;
@ -247,6 +252,7 @@ static void linphone_gtk_init_liblinphone(const char *config_file,
_linphone_gtk_enable_video(FALSE);
linphone_gtk_set_ui_config_int("videoselfview",0);
}
if (db_file) linphone_core_set_chat_database_path(the_core,db_file);
}
LinphoneCore *linphone_gtk_get_core(void){
@ -562,7 +568,7 @@ static gboolean linphone_gtk_iterate(LinphoneCore *lc){
if (id!=0){
ms_message("Updating window decorations");
#ifndef WIN32
w=gdk_window_foreign_new(id);
w=gdk_window_foreign_new((GdkNativeWindow)id);
#else
w=gdk_window_foreign_new((HANDLE)id);
#endif
@ -581,7 +587,7 @@ static gboolean linphone_gtk_iterate(LinphoneCore *lc){
if (id!=0){
ms_message("Updating window decorations for preview");
#ifndef WIN32
w=gdk_window_foreign_new(id);
w=gdk_window_foreign_new((GdkNativeWindow)id);
#else
w=gdk_window_foreign_new((HANDLE)id);
#endif
@ -744,37 +750,90 @@ static void linphone_gtk_update_call_buttons(LinphoneCall *call){
linphone_gtk_enable_conference_button(lc,FALSE);
}
update_video_title();
if (call) linphone_gtk_update_video_button(call);
if (call) {
linphone_gtk_update_video_button(call);
}
}
gchar *linphone_gtk_get_record_path(const LinphoneAddress *address, gboolean is_conference){
const char *dir=g_get_user_special_dir(G_USER_DIRECTORY_MUSIC);
const char *id="unknown";
char filename[256]={0};
char date[64]={0};
time_t curtime=time(NULL);
struct tm loctime;
#ifdef WIN32
loctime=*localtime(&curtime);
#else
localtime_r(&curtime,&loctime);
#endif
snprintf(date,sizeof(date)-1,"%i%02i%02i-%02i%02i",loctime.tm_year+1900,loctime.tm_mon+1,loctime.tm_mday, loctime.tm_hour, loctime.tm_min);
if (address){
id=linphone_address_get_username(address);
if (id==NULL) id=linphone_address_get_domain(address);
}
if (is_conference){
snprintf(filename,sizeof(filename)-1,"%s-conference-%s.wav",
linphone_gtk_get_ui_config("title","Linphone"),
date);
}else{
snprintf(filename,sizeof(filename)-1,"%s-call-%s-%s.wav",
linphone_gtk_get_ui_config("title","Linphone"),
date,
id);
}
return g_build_filename(dir,filename,NULL);
}
static gboolean linphone_gtk_start_call_do(GtkWidget *uri_bar){
const char *entered=gtk_entry_get_text(GTK_ENTRY(uri_bar));
if (linphone_core_invite(linphone_gtk_get_core(),entered)!=NULL) {
LinphoneCore *lc=linphone_gtk_get_core();
LinphoneAddress *addr=linphone_core_interpret_url(lc,entered);
if (addr!=NULL){
LinphoneCallParams *params=linphone_core_create_default_call_parameters(lc);
gchar *record_file=linphone_gtk_get_record_path(addr,FALSE);
linphone_call_params_set_record_file(params,record_file);
linphone_core_invite_address_with_params(lc,addr,params);
completion_add_text(GTK_ENTRY(uri_bar),entered);
linphone_address_destroy(addr);
linphone_call_params_destroy(params);
g_free(record_file);
}else{
linphone_gtk_call_terminated(NULL,NULL);
}
return FALSE;
}
static void accept_incoming_call(LinphoneCall *call){
LinphoneCore *lc=linphone_gtk_get_core();
LinphoneCallParams *params=linphone_core_create_default_call_parameters(lc);
gchar *record_file=linphone_gtk_get_record_path(linphone_call_get_remote_address(call),FALSE);
linphone_call_params_set_record_file(params,record_file);
linphone_core_accept_call_with_params(lc,call,params);
linphone_call_params_destroy(params);
}
static gboolean linphone_gtk_auto_answer(LinphoneCall *call){
if (linphone_call_get_state(call)==LinphoneCallIncomingReceived){
linphone_core_accept_call (linphone_gtk_get_core(),call);
linphone_call_unref(call);
LinphoneCallState state=linphone_call_get_state(call);
if (state==LinphoneCallIncomingReceived || state==LinphoneCallIncomingEarlyMedia){
accept_incoming_call(call);
}
return FALSE;
}
void linphone_gtk_start_call(GtkWidget *w){
LinphoneCore *lc=linphone_gtk_get_core();
LinphoneCall *call;
LinphoneCall *call=linphone_gtk_get_currently_displayed_call(NULL);
/*change into in-call mode, then do the work later as it might block a bit */
GtkWidget *mw=gtk_widget_get_toplevel(w);
GtkWidget *uri_bar=linphone_gtk_get_widget(mw,"uribar");
LinphoneCallState state= call ? linphone_call_get_state(call) : LinphoneCallIdle;
call=linphone_gtk_get_currently_displayed_call(NULL);
if (call!=NULL && linphone_call_get_state(call)==LinphoneCallIncomingReceived){
linphone_core_accept_call(lc,call);
if (state == LinphoneCallIncomingReceived || state == LinphoneCallIncomingEarlyMedia){
accept_incoming_call(call);
}else{
/*immediately disable the button and delay a bit the execution the linphone_core_invite()
so that we don't freeze the button. linphone_core_invite() might block for some hundreds of milliseconds*/
@ -807,7 +866,7 @@ void linphone_gtk_decline_clicked(GtkWidget *button){
void linphone_gtk_answer_clicked(GtkWidget *button){
LinphoneCall *call=linphone_gtk_get_currently_displayed_call(NULL);
if (call){
linphone_core_accept_call(linphone_gtk_get_core(),call);
accept_incoming_call(call);
linphone_gtk_show_main_window(); /* useful when the button is clicked on a notification */
}
}
@ -1064,13 +1123,13 @@ void linphone_gtk_notify(LinphoneCall *call, const char *msg){
NotifyNotification *n;
switch(linphone_call_get_state(call)){
case LinphoneCallError:
make_notification(_("Call error"),body=g_markup_printf_escaped("<span size=\"large\">%s</span>\n%s",msg,remote));
make_notification(_("Call error"),body=g_markup_printf_escaped("<b>%s</b>\n%s",msg,remote));
break;
case LinphoneCallEnd:
make_notification(_("Call ended"),body=g_markup_printf_escaped("<span size=\"large\">%s</span>",remote));
make_notification(_("Call ended"),body=g_markup_printf_escaped("<b>%s</b>",remote));
break;
case LinphoneCallIncomingReceived:
n=build_notification(_("Incoming call"),body=g_markup_printf_escaped("<span size=\"large\">%s</span>",remote));
n=build_notification(_("Incoming call"),body=g_markup_printf_escaped("<b>%s</b>",remote));
if (notify_actions_supported()) {
notify_notification_add_action (n,"answer", _("Answer"),
NOTIFY_ACTION_CALLBACK(linphone_gtk_answer_clicked),NULL,NULL);
@ -1080,7 +1139,7 @@ void linphone_gtk_notify(LinphoneCall *call, const char *msg){
show_notification(n);
break;
case LinphoneCallPausedByRemote:
make_notification(_("Call paused"),body=g_markup_printf_escaped(_("<span size=\"large\">by %s</span>"),remote));
make_notification(_("Call paused"),body=g_markup_printf_escaped(_("<b>by %s</b>"),remote));
break;
default:
break;
@ -1173,10 +1232,10 @@ static void linphone_gtk_call_state_changed(LinphoneCore *lc, LinphoneCall *call
break;
case LinphoneCallPausing:
linphone_gtk_enable_hold_button(call,TRUE,FALSE);
update_tab_header(call,FALSE);
linphone_gtk_call_update_tab_header(call,FALSE);
case LinphoneCallPausedByRemote:
linphone_gtk_in_call_view_set_paused(call);
update_tab_header(call,TRUE);
linphone_gtk_call_update_tab_header(call,TRUE);
break;
case LinphoneCallConnected:
linphone_gtk_enable_hold_button (call,TRUE,TRUE);
@ -1316,11 +1375,20 @@ static GtkWidget *create_icon_menu(){
return menu;
}
void linphone_gtk_save_main_window_position(GtkWindow* mw, GdkEvent *event, gpointer data){
gtk_window_get_position(GTK_WINDOW(mw), &main_window_x, &main_window_y);
}
static void handle_icon_click() {
GtkWidget *mw=linphone_gtk_get_main_window();
if (!gtk_window_is_active((GtkWindow*)mw)) {
if(!gtk_widget_is_drawable(mw)){
//we only move if window was hidden. If it was simply behind the window stack, ie, drawable, we keep it as it was
gtk_window_move (GTK_WINDOW(mw), main_window_x, main_window_y);
}
linphone_gtk_show_main_window();
} else {
linphone_gtk_save_main_window_position((GtkWindow*)mw, NULL, NULL);
gtk_widget_hide(mw);
}
}
@ -1365,10 +1433,10 @@ static gboolean do_icon_blink(GtkStatusIcon *gi){
void linphone_gtk_status_icon_set_blinking(gboolean val){
#ifdef HAVE_GTK_OSX
static gint attention_id;
GtkOSXApplication *theMacApp=(GtkOSXApplication*)g_object_new(GTK_TYPE_OSX_APPLICATION, NULL);
GtkosxApplication *theMacApp=gtkosx_application_get();
if (val)
attention_id=gtk_osxapplication_attention_request(theMacApp,CRITICAL_REQUEST);
else gtk_osxapplication_cancel_attention_request(theMacApp,attention_id);
attention_id=gtkosx_application_attention_request(theMacApp,CRITICAL_REQUEST);
else gtkosx_application_cancel_attention_request(theMacApp,attention_id);
#else
if (icon!=NULL){
guint tout;
@ -1444,7 +1512,7 @@ void linphone_gtk_load_identities(void){
static void linphone_gtk_dtmf_pressed(GtkButton *button){
const char *label=(char *)g_object_get_data(G_OBJECT(button),"label");
GtkWidget *uri_bar=linphone_gtk_get_widget(gtk_widget_get_toplevel(GTK_WIDGET(button)),"uribar");
GtkWidget *uri_bar=linphone_gtk_get_widget(linphone_gtk_get_main_window(),"uribar");
int pos=-1;
gtk_editable_insert_text(GTK_EDITABLE(uri_bar),label,1,&pos);
linphone_core_play_dtmf (linphone_gtk_get_core(),label[0],-1);
@ -1458,8 +1526,8 @@ static void linphone_gtk_dtmf_released(GtkButton *button){
}
static void linphone_gtk_connect_digits(void){
GtkContainer *cont=GTK_CONTAINER(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"dtmf_table"));
static void linphone_gtk_connect_digits(GtkWidget *w){
GtkContainer *cont=GTK_CONTAINER(linphone_gtk_get_widget(w,"dtmf_table"));
GList *children=gtk_container_get_children(cont);
GList *elem;
for(elem=children;elem!=NULL;elem=elem->next){
@ -1497,23 +1565,17 @@ static void linphone_gtk_configure_main_window(){
static const char *home;
static const char *start_call_icon;
static const char *add_call_icon;
//static const char *stop_call_icon;
static const char *search_icon;
static gboolean update_check_menu;
static gboolean buttons_have_borders;
static gboolean show_abcd;
GtkWidget *w=linphone_gtk_get_main_window();
GHashTable *contacts_history;
contacts_history=g_hash_table_new_full(g_str_hash, g_str_equal,g_free, NULL);
g_object_set_data(G_OBJECT(w),"history",(gpointer)contacts_history);
if (!config_loaded){
title=linphone_gtk_get_ui_config("title","Linphone");
home=linphone_gtk_get_ui_config("home","http://www.linphone.org");
start_call_icon=linphone_gtk_get_ui_config("start_call_icon","startcall-green.png");
add_call_icon=linphone_gtk_get_ui_config("add_call_icon","addcall-green.png");
//stop_call_icon=linphone_gtk_get_ui_config("stop_call_icon","stopcall-small.png");
search_icon=linphone_gtk_get_ui_config("directory_search_icon",NULL);
update_check_menu=linphone_gtk_get_ui_config_int("update_check_menu",0);
buttons_have_borders=linphone_gtk_get_ui_config_int("buttons_border",1);
@ -1559,16 +1621,10 @@ static void linphone_gtk_configure_main_window(){
*/
}
{
GdkPixbuf *pbuf=create_pixbuf("dialer-orange.png");
GdkPixbuf *pbuf=create_pixbuf("dialer.png");
if (pbuf) {
GtkImage *img=GTK_IMAGE(linphone_gtk_get_widget(w,"keypad_tab_icon"));
int w,h;
GdkPixbuf *scaled;
gtk_icon_size_lookup(GTK_ICON_SIZE_MENU,&w,&h);
scaled=gdk_pixbuf_scale_simple(pbuf,w,h,GDK_INTERP_BILINEAR);
gtk_image_set_from_pixbuf(img,scaled);
g_object_unref(G_OBJECT(scaled));
g_object_unref(G_OBJECT(pbuf));
GtkButton *button=GTK_BUTTON(linphone_gtk_get_widget(w,"keypad"));
gtk_button_set_image(button,gtk_image_new_from_pixbuf (pbuf));
}
}
if (linphone_gtk_can_manage_accounts()) {
@ -1577,13 +1633,7 @@ static void linphone_gtk_configure_main_window(){
if (update_check_menu){
gtk_widget_show(linphone_gtk_get_widget(w,"versioncheck_item"));
}
if (!show_abcd){
gtk_widget_hide(linphone_gtk_get_widget(w,"dtmf_A"));
gtk_widget_hide(linphone_gtk_get_widget(w,"dtmf_B"));
gtk_widget_hide(linphone_gtk_get_widget(w,"dtmf_C"));
gtk_widget_hide(linphone_gtk_get_widget(w,"dtmf_D"));
gtk_table_resize(GTK_TABLE(linphone_gtk_get_widget(w,"dtmf_table")),4,3);
}
g_object_set_data(G_OBJECT(w),"show_abcd",GINT_TO_POINTER(show_abcd));
}
void linphone_gtk_manage_login(void){
@ -1598,7 +1648,6 @@ void linphone_gtk_manage_login(void){
}
}
gboolean linphone_gtk_close(GtkWidget *mw){
/*shutdown calls if any*/
LinphoneCore *lc=linphone_gtk_get_core();
@ -1647,24 +1696,42 @@ void linphone_gtk_init_dtmf_table(GtkWidget *mw){
g_object_set_data(G_OBJECT(linphone_gtk_get_widget(mw,"dtmf_0")),"label","0");
g_object_set_data(G_OBJECT(linphone_gtk_get_widget(mw,"dtmf_#")),"label","#");
g_object_set_data(G_OBJECT(linphone_gtk_get_widget(mw,"dtmf_*")),"label","*");
}
void linphone_gtk_create_keypad(GtkWidget *button){
GtkWidget *mw=linphone_gtk_get_main_window();
GtkWidget *k=(GtkWidget *)g_object_get_data(G_OBJECT(mw),"keypad");
if(k!=NULL){
gtk_widget_destroy(k);
}
GtkWidget *keypad=linphone_gtk_create_window("keypad");
linphone_gtk_connect_digits(keypad);
linphone_gtk_init_dtmf_table(keypad);
g_object_set_data(G_OBJECT(mw),"keypad",(gpointer)keypad);
if(!GPOINTER_TO_INT(g_object_get_data(G_OBJECT(mw),"show_abcd"))){
gtk_widget_hide(linphone_gtk_get_widget(keypad,"dtmf_A"));
gtk_widget_hide(linphone_gtk_get_widget(keypad,"dtmf_B"));
gtk_widget_hide(linphone_gtk_get_widget(keypad,"dtmf_C"));
gtk_widget_hide(linphone_gtk_get_widget(keypad,"dtmf_D"));
gtk_table_resize(GTK_TABLE(linphone_gtk_get_widget(keypad,"dtmf_table")),4,3);
}
gtk_widget_show(keypad);
}
static void linphone_gtk_init_main_window(){
GtkWidget *main_window;
linphone_gtk_configure_main_window();
linphone_gtk_manage_login();
load_uri_history();
linphone_gtk_load_identities();
linphone_gtk_set_my_presence(linphone_core_get_presence_info(linphone_gtk_get_core()));
linphone_gtk_show_friends();
linphone_gtk_connect_digits();
linphone_core_reset_missed_calls_count(linphone_gtk_get_core());
main_window=linphone_gtk_get_main_window();
linphone_gtk_call_log_update(main_window);
linphone_gtk_init_dtmf_table(main_window);
linphone_gtk_update_call_buttons (NULL);
g_object_set_data(G_OBJECT(main_window),"keypad",NULL);
g_object_set_data(G_OBJECT(main_window),"is_conf",GINT_TO_POINTER(FALSE));
/*prevent the main window from being destroyed by a user click on WM controls, instead we hide it*/
g_signal_connect (G_OBJECT (main_window), "delete-event",
@ -1672,17 +1739,16 @@ static void linphone_gtk_init_main_window(){
#ifdef HAVE_GTK_OSX
{
GtkWidget *menubar=linphone_gtk_get_widget(main_window,"menubar1");
GtkOSXApplication *theMacApp = (GtkOSXApplication*)g_object_new(GTK_TYPE_OSX_APPLICATION, NULL);
gtk_osxapplication_set_menu_bar(theMacApp,GTK_MENU_SHELL(menubar));
GtkosxApplication *theMacApp = gtkosx_application_get();
gtkosx_application_set_menu_bar(theMacApp,GTK_MENU_SHELL(menubar));
gtk_widget_hide(menubar);
gtk_osxapplication_ready(theMacApp);
gtkosx_application_ready(theMacApp);
}
g_signal_connect(G_OBJECT(main_window), "window-state-event",G_CALLBACK(on_window_state_event), NULL);
#endif
linphone_gtk_check_menu_items();
}
void linphone_gtk_log_handler(OrtpLogLevel lev, const char *fmt, va_list args){
if (verbose){
const char *lname="undef";
@ -1787,6 +1853,8 @@ int main(int argc, char *argv[]){
GtkSettings *settings;
GdkPixbuf *pbuf;
const char *app_name="Linphone";
LpConfig *factory;
const char *db_file;
#if !GLIB_CHECK_VERSION(2, 31, 0)
g_thread_init(NULL);
@ -1862,6 +1930,11 @@ int main(int argc, char *argv[]){
since we want to have had time to change directory and to parse
the options, in case we needed to access the working directory */
factory_config_file = linphone_gtk_get_factory_config_file();
if (factory_config_file){
factory=lp_config_new(NULL);
lp_config_read_file(factory,factory_config_file);
app_name=lp_config_get_string(factory,"GtkUi","title","Linphone");
}
if (linphone_gtk_init_instance(app_name, addr_to_call) == FALSE){
g_warning("Another running instance of linphone has been detected. It has been woken-up.");
@ -1874,7 +1947,7 @@ int main(int argc, char *argv[]){
add_pixmap_directory(PACKAGE_DATA_DIR "/pixmaps/linphone");
#ifdef HAVE_GTK_OSX
GtkOSXApplication *theMacApp = (GtkOSXApplication*)g_object_new(GTK_TYPE_OSX_APPLICATION, NULL);
GtkosxApplication *theMacApp = gtkosx_application_get();
g_signal_connect(G_OBJECT(theMacApp),"NSApplicationDidBecomeActive",(GCallback)linphone_gtk_show_main_window,NULL);
g_signal_connect(G_OBJECT(theMacApp),"NSApplicationWillTerminate",(GCallback)gtk_main_quit,NULL);
/*never block termination:*/
@ -1888,7 +1961,8 @@ int main(int argc, char *argv[]){
linphone_gtk_create_log_window();
linphone_core_enable_logs_with_cb(linphone_gtk_log_handler);
linphone_gtk_init_liblinphone(config_file, factory_config_file);
db_file=linphone_gtk_message_storage_get_db_file(NULL);
linphone_gtk_init_liblinphone(config_file, factory_config_file, db_file);
g_set_application_name(app_name);
pbuf=create_pixbuf(linphone_gtk_get_ui_config("icon",LINPHONE_ICON));

File diff suppressed because it is too large Load diff

View file

@ -639,53 +639,115 @@
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<child>
<object class="GtkVButtonBox" id="vbuttonbox3">
<object class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkRadioButton" id="no_nat">
<property name="label" translatable="yes">Direct connection to the Internet</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="linphone_gtk_no_firewall_toggled" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="vbox4">
<object class="GtkVButtonBox" id="vbuttonbox3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkRadioButton" id="use_nat_address">
<property name="label" translatable="yes">Behind NAT / Firewall (specify gateway IP below)</property>
<object class="GtkRadioButton" id="no_nat">
<property name="label" translatable="yes">Direct connection to the Internet</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="linphone_gtk_no_firewall_toggled" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="use_nat_address">
<property name="label" translatable="yes">Behind NAT / Firewall (specify gateway IP )</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="draw_indicator">True</property>
<property name="group">no_nat</property>
<signal name="toggled" handler="linphone_gtk_use_nat_address_toggled" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="use_stun">
<property name="label" translatable="yes">Behind NAT / Firewall (use STUN to resolve)</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="draw_indicator">True</property>
<property name="group">no_nat</property>
<signal name="toggled" handler="linphone_gtk_use_stun_toggled" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="use_ice">
<property name="label" translatable="yes">Behind NAT / Firewall (use ICE)</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="draw_indicator">True</property>
<property name="group">no_nat</property>
<signal name="toggled" handler="linphone_gtk_use_ice_toggled" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="use_upnp">
<property name="label" translatable="yes">Behind NAT / Firewall (use uPnP)</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="draw_indicator">True</property>
<property name="group">no_nat</property>
<signal name="toggled" handler="linphone_gtk_use_upnp_toggled" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="vbox5">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkHBox" id="hbox21">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="homogeneous">True</property>
<child>
<object class="GtkLabel" id="label39">
<property name="visible">True</property>
@ -705,6 +767,8 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="invisible_char">•</property>
<property name="invisible_char_set">True</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
<property name="primary_icon_sensitive">True</property>
@ -720,7 +784,53 @@
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkHBox" id="hbox24">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="homogeneous">True</property>
<child>
<object class="GtkLabel" id="label42">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">Stun server:</property>
<property name="justify">right</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="stun_server">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="invisible_char">●</property>
<property name="invisible_char_set">True</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
<property name="primary_icon_sensitive">True</property>
<property name="secondary_icon_sensitive">True</property>
<signal name="changed" handler="linphone_gtk_stun_server_changed" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
@ -731,85 +841,6 @@
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="use_stun">
<property name="label" translatable="yes">Behind NAT / Firewall (use STUN to resolve)</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="draw_indicator">True</property>
<property name="group">no_nat</property>
<signal name="toggled" handler="linphone_gtk_use_stun_toggled" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="use_ice">
<property name="label" translatable="yes">Behind NAT / Firewall (use ICE)</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_action_appearance">False</property>
<property name="draw_indicator">True</property>
<property name="group">no_nat</property>
<signal name="toggled" handler="linphone_gtk_use_ice_toggled" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkHBox" id="hbox24">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
<object class="GtkLabel" id="label42">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="label" translatable="yes">Stun server:</property>
<property name="justify">right</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="stun_server">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="invisible_char">●</property>
<property name="invisible_char_set">True</property>
<property name="primary_icon_activatable">False</property>
<property name="secondary_icon_activatable">False</property>
<property name="primary_icon_sensitive">True</property>
<property name="secondary_icon_sensitive">True</property>
<signal name="changed" handler="linphone_gtk_stun_server_changed" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
</object>
</child>
<child type="label">

View file

@ -131,6 +131,13 @@ void linphone_gtk_update_my_port(GtkWidget *w){
linphone_core_set_sip_transports(lc,&tr);
}
void linphone_gtk_set_propety_entry(GtkWidget *w, gboolean stunServer, gboolean ip){
GtkWidget *stun_entry=linphone_gtk_get_widget(gtk_widget_get_toplevel(w),"stun_server");
GtkWidget *ip_entry=linphone_gtk_get_widget(gtk_widget_get_toplevel(w),"nat_address");
gtk_widget_set_sensitive(stun_entry,stunServer);
gtk_widget_set_sensitive(ip_entry,ip);
}
void linphone_gtk_stun_server_changed(GtkWidget *w){
const gchar *addr=gtk_entry_get_text(GTK_ENTRY(w));
linphone_core_set_stun_server(linphone_gtk_get_core(),addr);
@ -217,23 +224,38 @@ void linphone_gtk_max_video_port_changed(GtkWidget *w){
}
void linphone_gtk_no_firewall_toggled(GtkWidget *w){
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)))
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))){
linphone_gtk_set_propety_entry(w,FALSE,FALSE);
linphone_core_set_firewall_policy(linphone_gtk_get_core(),LinphonePolicyNoFirewall);
}
}
void linphone_gtk_use_nat_address_toggled(GtkWidget *w){
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)))
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))){
linphone_gtk_set_propety_entry(w,FALSE,TRUE);
linphone_core_set_firewall_policy(linphone_gtk_get_core(),LinphonePolicyUseNatAddress);
}
}
void linphone_gtk_use_stun_toggled(GtkWidget *w){
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)))
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))){
linphone_gtk_set_propety_entry(w,TRUE,FALSE);
linphone_core_set_firewall_policy(linphone_gtk_get_core(),LinphonePolicyUseStun);
}
}
void linphone_gtk_use_ice_toggled(GtkWidget *w){
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)))
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))){
linphone_gtk_set_propety_entry(w,TRUE,FALSE);
linphone_core_set_firewall_policy(linphone_gtk_get_core(),LinphonePolicyUseIce);
}
}
void linphone_gtk_use_upnp_toggled(GtkWidget *w){
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))){
linphone_gtk_set_propety_entry(w,FALSE,FALSE);
linphone_core_set_firewall_policy(linphone_gtk_get_core(),LinphonePolicyUseUpnp);
}
}
void linphone_gtk_mtu_changed(GtkWidget *w){
@ -773,6 +795,7 @@ static LangCodes supported_langs[]={
{ "zh_TW" , N_("Traditional Chinese") },
{ "nb_NO" , N_("Norwegian") },
{ "he" , N_("Hebrew") },
{ "sr" , N_("Serbian") },
{ NULL , NULL }
};
@ -967,7 +990,8 @@ static void linphone_gtk_show_media_encryption(GtkWidget *pb){
}
g_signal_connect(G_OBJECT(combo),"changed",(GCallback)linphone_gtk_media_encryption_changed,NULL);
}
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"media_encryption_mandatory")),linphone_core_is_media_encryption_mandatory(lc));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"media_encryption_mandatory")),
linphone_core_is_media_encryption_mandatory(lc));
g_object_unref(G_OBJECT(model));
}
@ -1010,10 +1034,8 @@ void linphone_gtk_show_parameters(void){
if (pb==NULL) {
pb=linphone_gtk_create_window("parameters");
g_object_set_data(G_OBJECT(mw),"parameters",pb);
ms_error("linphone_gtk_show_paramters: create");
}else {
gtk_widget_show(pb);
ms_error("linphone_gtk_show_parameters: show");
return;
}
codec_list=linphone_gtk_get_widget(pb,"codec_list");
@ -1023,21 +1045,21 @@ void linphone_gtk_show_parameters(void){
linphone_core_ipv6_enabled(lc));
linphone_core_get_sip_transports(lc,&tr);
if (tr.tcp_port > 0) {
gtk_combo_box_set_active(GTK_COMBO_BOX(linphone_gtk_get_widget(pb,"proto_combo")), 1);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb,"proto_port")),
if (tr.tcp_port > 0) {
gtk_combo_box_set_active(GTK_COMBO_BOX(linphone_gtk_get_widget(pb,"proto_combo")), 1);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb,"proto_port")),
tr.tcp_port);
}
else if (tr.tls_port > 0) {
gtk_combo_box_set_active(GTK_COMBO_BOX(linphone_gtk_get_widget(pb,"proto_combo")), 2);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb,"proto_port")),
}
else if (tr.tls_port > 0) {
gtk_combo_box_set_active(GTK_COMBO_BOX(linphone_gtk_get_widget(pb,"proto_combo")), 2);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb,"proto_port")),
tr.tls_port);
}
else {
gtk_combo_box_set_active(GTK_COMBO_BOX(linphone_gtk_get_widget(pb,"proto_combo")), 0);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb,"proto_port")),
}
else {
gtk_combo_box_set_active(GTK_COMBO_BOX(linphone_gtk_get_widget(pb,"proto_combo")), 0);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb,"proto_port")),
tr.udp_port);
}
}
linphone_core_get_audio_port_range(lc, &min_port, &max_port);
gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb, "audio_min_rtp_port")), min_port);
@ -1074,7 +1096,14 @@ void linphone_gtk_show_parameters(void){
case LinphonePolicyUseIce:
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"use_ice")),TRUE);
break;
case LinphonePolicyUseUpnp:
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"use_upnp")),TRUE);
break;
}
if(!linphone_core_upnp_available(lc)) {
gtk_widget_hide(linphone_gtk_get_widget(pb,"use_upnp"));
}
mtu=linphone_core_get_mtu(lc);
if (mtu<=0){
gtk_widget_set_sensitive(linphone_gtk_get_widget(pb,"mtu"),FALSE);

0
gtk/update.c Executable file → Normal file
View file

View file

@ -18,9 +18,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.linphone.core;
/**
* Enum representing the direction of a call.
**/
public class CallDirection {
/**
* outgoing calls*
* */
public static CallDirection Outgoing = new CallDirection("CallOutgoing");
/**
* incoming calls
*/
public static CallDirection Incoming = new CallDirection("Callincoming");
private String mStringValue;
private CallDirection(String aStringValue) {

View file

@ -39,21 +39,48 @@ public interface LinphoneAddress {
*/
public String getUserName();
/**
*
* Domain name
* @return null if not set
*/
public String getDomain();
/**
* Port as String
* @return null if not set
*/
public String getPort();
/**
* Port as integer value.
* @return negative value if not set if not set
*/
public int getPortInt();
/**
* set display name
* @param name
*/
public void setDisplayName(String name);
/**
* set user name
* @param username
*/
public void setUserName(String username);
/**
* set domain name
* @param domain
*/
public void setDomain(String domain);
/**
* set port as String
* @param port, null if not set
*/
public void setPort(String port);
/**
* set port as int
* @param port, negative value if not set
*/
public void setPortInt(int port);
/**
* Removes address's tags and uri headers so that it is displayable to the user.
**/
public void clean();
/**

View file

@ -20,7 +20,7 @@ package org.linphone.core;
/**
* Object holding authentication information.
* In most case, authentication information consists of a username and password. Sometimes, a userid is required by proxy, and realm can be useful to discriminate different SIP domains.
*<br>This object is instanciated using {@link LinphoneCoreFactory#createAuthInfo(String, String, String)}.
*<br>This object is instantiated using either {@link LinphoneCoreFactory#createAuthInfo(String, String, String)} or {@link LinphoneCoreFactory#createAuthInfo(String, String, String, String, String)}.
*<br>
*Once created and filled, a LinphoneAuthInfo must be added to the LinphoneCore in order to become known and used automatically when needed.
*Use {@link LinphoneCore#addAuthInfo(LinphoneAuthInfo)} for that purpose.
@ -63,6 +63,26 @@ public interface LinphoneAuthInfo {
* @param realm
*/
void setRealm(String realm);
/**
* get auth userid has used in authentication header. If null, username is taken for authentication
* @return auth userid
*/
String getUserId();
/**
* set auth userid has used in authentication header. If null, username is taken for authentication
*
*/
void setUserId(String userid);
/**
* get ha1
* @return ha1
*/
String getHa1();
/**
* set ha1
*/
void setHa1(String ha1);
}

View file

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

View file

@ -24,7 +24,11 @@ package org.linphone.core;
import java.util.Vector;
/**
* Object representing a call log.
*
*
**/
public interface LinphoneCallLog {
/**
* Represents call status
@ -91,26 +95,30 @@ public interface LinphoneCallLog {
public CallDirection getDirection();
/**
* get status of this call
* @return
* @return CallStatus
*/
public CallStatus getStatus();
/**
* @return a human readble String with the start date/time of the call
* A human readable String with the start date/time of the call
* @return String
*/
public String getStartDate();
/**
* @return a timestamp of the start date/time of the call in milliseconds since January 1st 1970
* A timestamp of the start date/time of the call in milliseconds since January 1st 1970
* @return long
*/
public long getTimestamp();
/**
* @return the call duration, in seconds
* The call duration, in seconds
* @return int
*/
public int getCallDuration();
/**
* @return the call id from signaling
* Call id from signaling
* @return int
*/
public int getCallId();
}

View file

@ -72,4 +72,25 @@ public interface LinphoneCallParams {
* @return true if low bandwidth has been configured/detected
*/
boolean isLowBandwidthEnabled();
/**
* Set a path to file where the call will be recorded.
* Actual start of the recording is controlled by LinphoneCall.startRecording().
**/
void setRecordFile(String path);
/**
* Add a custom header to be used for the call for which these call params are used.
* @param name header name
* @param value header value
*/
void addCustomHeader(String name, String value);
/**
* Returns the value of a custom header given its name.
* If no header with that name exists, then null is returned.
* @param name
* @return value for the header, or null if it doesn't exist.
*/
String getCustomHeader(String name);
}

View file

@ -121,25 +121,25 @@ public interface LinphoneCallStats {
public float getUploadBandwidth();
/**
* Get the sender loss rate since last report
* Get the local loss rate since last report
* @return The sender loss rate
*/
public float getSenderLossRate();
/**
* Get the receiver loss rate since last report
* Get the remote reported loss rate since last report
* @return The receiver loss rate
*/
public float getReceiverLossRate();
/**
* Get the sender interarrival jitter
* Get the local interarrival jitter
* @return The interarrival jitter at last emitted sender report
*/
public float getSenderInterarrivalJitter();
/**
* Get the receiver interarrival jitter
* Get the remote reported interarrival jitter
* @return The interarrival jitter at last received receiver report
*/
public float getReceiverInterarrivalJitter();
@ -161,4 +161,16 @@ public interface LinphoneCallStats {
* @return The jitter buffer size in milliseconds
*/
public float getJitterBufferSize();
/**
* Get the local loss rate. Unlike getSenderLossRate() that returns this loss rate "since last emitted RTCP report", the value returned here is updated every second.
* @return The local loss rate percentage.
**/
public float getLocalLossRate();
/**
* Get the local late packets rate. The value returned here is updated every second.
* @return The local late rate percentage.
**/
public float getLocalLateRate();
}

View file

@ -63,7 +63,7 @@ public interface LinphoneChatMessage {
*
* @return text sent along with the message
*/
String getMessage();
String getText();
/**
* get peer address associated to this LinphoneChatMessage
@ -92,4 +92,24 @@ public interface LinphoneChatMessage {
* @param url ex: access-type=URL; URL="http://www.foo.com/file"
*/
void setExternalBodyUrl(String url);
/**
* Add a custom header into the message.
* @param name
* @param value
*/
void addCustomHeader(String name, String value);
/**
* Obtain a header value.
* @param name
* @return the value of the header, or null if not found.
*/
String getCustomHeader(String name);
/**
* Gets the time at which the message was sent
* @return the time in milliseconds
*/
long getTime();
}

View file

@ -20,6 +20,9 @@ package org.linphone.core;
import java.util.Vector;
import org.linphone.core.LinphoneCall.State;
import org.linphone.mediastream.video.capture.hwconf.AndroidCameraConfiguration;
/**
* Linphone core main object created by method {@link LinphoneCoreFactory#createLinphoneCore(LinphoneCoreListener, String, String, Object)}.
*
@ -141,6 +144,10 @@ public interface LinphoneCore {
* Use ICE.
*/
static public FirewallPolicy UseIce = new FirewallPolicy(3,"UseIce");
/**
* Use uPnP.
*/
static public FirewallPolicy UseUpnp = new FirewallPolicy(4,"UseUpnp");
private final int mValue;
private final String mStringValue;
@ -168,11 +175,22 @@ public interface LinphoneCore {
}
/**
* Signaling transports ports.
* Linphone core SIP transport ports.
* Use with {@link LinphoneCore#setSignalingTransportPorts(Transports)}
* @ingroup initializing
*/
static public class Transports {
/**
* udp port to listening on, negative value if not set
* */
public int udp;
/**
* tcp port to listening on, negative value if not set
* */
public int tcp;
/**
* tls port to listening on, negative value if not set
* */
public int tls;
public Transports() {};
@ -278,6 +296,56 @@ public interface LinphoneCore {
return mValue;
}
}
static public class UpnpState {
static private Vector<UpnpState> values = new Vector<UpnpState>();
/**
* Idle
*/
static public UpnpState Idle = new UpnpState(0, "Idle");
/**
* Pending
*/
static public UpnpState Pending = new UpnpState(1, "Pending");
/**
* Adding
*/
static public UpnpState Adding = new UpnpState(2, "Adding");
/**
* Removing
*/
static public UpnpState Removing = new UpnpState(3, "Removing");
/**
* Not Available
*/
static public UpnpState NotAvailable = new UpnpState(4, "Not available");
/**
* Ok
*/
static public UpnpState Ok = new UpnpState(5, "Ok");
/**
* Ko
*/
static public UpnpState Ko = new UpnpState(6, "Ko");
protected final int mValue;
private final String mStringValue;
private UpnpState(int value, String stringValue) {
mValue = value;
values.addElement(this);
mStringValue = stringValue;
}
public static UpnpState fromInt(int value) {
for (int i = 0; i < values.size(); i++) {
UpnpState mstate = (UpnpState) values.elementAt(i);
if (mstate.mValue == value) return mstate;
}
throw new RuntimeException("UpnpState not found [" + value + "]");
}
public String toString() {
return mStringValue;
}
}
/**
* Set the context of creation of the LinphoneCore.
@ -335,10 +403,10 @@ public interface LinphoneCore {
public LinphoneCall invite(String destination)throws LinphoneCoreException;
/**
* Initiates an outgoing call given a destination LinphoneAddress
*<br>The LinphoneAddress can be constructed directly using linphone_address_new(), or created by linphone_core_interpret_url(). The application doesn't own a reference to the returned LinphoneCall object. Use linphone_call_ref() to safely keep the LinphoneCall pointer valid within your application.
*<br>The LinphoneAddress can be constructed directly using {@link LinphoneCoreFactory#createLinphoneAddress} , or created {@link LinphoneCore#interpretUrl(String)}. .
* @param to the destination of the call (sip address).
* @return LinphoneCall
* @throws LinphoneCoreException
* @return linphone call
* @throws LinphoneCoreException if linphone call cannot be created
*/
public LinphoneCall invite(LinphoneAddress to)throws LinphoneCoreException;
/**
@ -346,6 +414,12 @@ public interface LinphoneCore {
* @param aCall to be terminated
*/
public void terminateCall(LinphoneCall aCall);
/**
* Declines an incoming call, providing a reason for declining it.
* @param call the LinphoneCall, must be in the {@link LinphoneCall.State#IncomingReceived} state.
* @param reason the reason for rejecting the call: {@link Reason#Declined} or {@link Reason#Busy}
*/
public void declineCall(LinphoneCall aCall, Reason reason);
/**
* Returns The LinphoneCall the current call if one is in call
*
@ -359,7 +433,7 @@ public interface LinphoneCore {
public LinphoneAddress getRemoteAddress();
/**
*
* @return TRUE if there is a call running or pending.
* @return true if there is a call running or pending.
*/
public boolean isIncall();
/**
@ -424,8 +498,6 @@ public interface LinphoneCore {
*/
public void deferCallUpdate(LinphoneCall aCall) throws LinphoneCoreException;
public void startRinging();
/**
* @return a list of LinphoneCallLog
*/
@ -441,7 +513,7 @@ public interface LinphoneCore {
*/
public void setNetworkReachable(boolean isReachable);
/**
*
* Get network state has known by {@link LinphoneCore}
* @return if false, there is no network connection.
*/
public boolean isNetworkReachable();
@ -483,16 +555,16 @@ public interface LinphoneCore {
/**
* Initiate a dtmf signal if in call
* @param number
* @param send dtmf ['0'..'9'] | '#', '*'
*/
void sendDtmf(char number);
/**
* Initiate a dtmf signal to the speaker if not in call.
* Sending of the DTMF is done in another function.
* @param number
* @param dtmf ['0'..'9'] | '#', '*'
* @param duration in ms , -1 for unlimited
*/
void playDtmf(char number,int duration);
void playDtmf(char dtmf,int duration);
/**
* stop current dtmf
*/
@ -502,23 +574,43 @@ public interface LinphoneCore {
* remove all call logs
*/
void clearCallLogs();
/***
* get payload type from mime type, clock rate, and number of channels.-
*
* return null if not found
*/
/**
* Get payload type from mime type and clock rate
*
* This function searches in audio and video codecs for the given payload type name and clockrate.
* @param mime payload mime type (I.E SPEEX, PCMU, VP8)
* @param clockRate (I.E 8000, 16000, 90000, ...)
* @param channels number of channels
* @return Returns null if not found.
*/
PayloadType findPayloadType(String mime, int clockRate, int channels);
/***
* get payload type from mime type and clock rate..
*
* return null if not found
* Same as @{link {@link #findPayloadType(String, int, int)} but ignoring channels params
* @param mime payload mime type (I.E SPEEX, PCMU, VP8)
* @param clockRate (I.E 8000, 16000, 90000, ...)
* @return null if not found
*/
PayloadType findPayloadType(String mime, int clockRate);
/***
* get payload type from mime type
* Same as @{link {@link #findPayloadType(String, int, int)} but ignoring channels and clock rate params
* @param mime payload mime type (I.E SPEEX, PCMU, VP8)
* @return null if not found
*/
PayloadType findPayloadType(String mime);
/**
* not implemented yet
* @param pt
* @param enable
* @throws LinphoneCoreException
* Enable payload type
* @param pt payload type to enable, can be retrieve from {@link #findPayloadType}
* @param true if enabled
* @exception LinphoneCoreException
*
*/
void enablePayloadType(PayloadType pt, boolean enable) throws LinphoneCoreException;
/**
@ -537,13 +629,28 @@ public interface LinphoneCore {
*/
boolean isEchoLimiterEnabled();
/**
* @param transports used for signaling (TCP, UDP and TLS)
* Set transport ports linphone core will listen on
* @param local transports ports used for signaling (TCP, UDP and TLS)
*/
void setSignalingTransportPorts(Transports transports);
/**
/**Get
* @return transports used for signaling (TCP, UDP, TLS)
*/
Transports getSignalingTransportPorts();
/**
* Assign a dscp value for the SIP socket.
* DSCP is an IP packet field used to indicate the type of routing service to routers.
* @param dscp
*/
void setSipDscp(int dscp);
/**
* Get DSCP used for SIP socket.
* @return the DSCP value used for the SIP socket.
*/
int getSipDscp();
/**
* Activates or deactivates the speaker.
* @param value
@ -574,12 +681,36 @@ public interface LinphoneCore {
* @return {@link LinphoneChatRoom} where messaging can take place.
*/
LinphoneChatRoom createChatRoom(String to);
/**
* Set the native video window id where the video is to be displayed.
* On Android, it must be of type {@link AndroidVideoWindowImpl}
* @param video window of type {@link AndroidVideoWindowImpl}
**/
void setVideoWindow(Object w);
/**
* Set the native video window id where the video preview is to be displayed.
* On Android, it must of type {@link SurfaceView}
* @param video window of type {@link SurfaceView}
**/
void setPreviewWindow(Object w);
/**
* Tells the core the device current orientation. This can be used by capture filters
* on mobile devices to select between portrait/landscape mode and to produce properly
* oriented images. The exact meaning of the value in rotation if left to each device
* specific implementations.
*@param rotation . Android supported values are 0, 90, 180 and 270.
*
**/
void setDeviceRotation(int rotation);
/**
* Sets the active video device.
*
* @param id of the video device as returned by {@link AndroidCameraConfiguration#retrieveCameras}
**/
void setVideoDevice(int id);
/**
* Returns the id of the currently active video device as found in {@link AndroidCameraConfiguration#retrieveCameras}.
**/
int getVideoDevice();
/**
@ -607,6 +738,7 @@ public interface LinphoneCore {
*/
void setStunServer(String stun_server);
/**
* Get STUN server
* @return stun server address if previously set.
*/
String getStunServer();
@ -620,11 +752,35 @@ public interface LinphoneCore {
* @return previously set firewall policy.
*/
FirewallPolicy getFirewallPolicy();
/**
* Initiates an outgoing call given a destination LinphoneAddress
*
* @param addr the destination of the call {@link #LinphoneAddress }.
* @param params call parameters {@link #LinphoneCallParams }
*
*<br>The LinphoneAddress can be constructed directly using {@link LinphoneCoreFactory#createLinphoneAddress} , or created {@link LinphoneCore#interpretUrl(String)}. .
*
* @return a {@link #LinphoneCall LinphoneCall} object
* @throws LinphoneCoreException in case of failure
**/
LinphoneCall inviteAddressWithParams(LinphoneAddress destination, LinphoneCallParams params) throws LinphoneCoreException ;
/**
* Updates a running call according to supplied call parameters or parameters changed in the LinphoneCore.
*
* In this version this is limited to the following use cases:
* - setting up/down the video stream according to the video parameter of the {@link LinphoneCallParams} (see {@link LinphoneCallParams#enableVideo} ).
* - changing the size of the transmitted video after calling {@link LinphoneCore#setPreferredVideoSize(VideoSize)}
*
* In case no changes are requested through the {@link LinphoneCallParams} argument, then this argument can be omitted and set to null.
* @param call the {@link LinphoneCall} to be updated
* @param params the new {@link LinphoneCallParams call parameters} to use. (may be NULL)
* @return 0 if successful, -1 otherwise.
**/
int updateCall(LinphoneCall call, LinphoneCallParams params);
/**
* Get default call parameters reflecting current linphone core configuration
* @return LinphoneCallParams
*/
LinphoneCallParams createDefaultCallParameters();
/**
@ -636,7 +792,7 @@ public interface LinphoneCore {
/**
* gets the path to a wav file used for ringing.
*
* @param null if not set
* @return null if not set
*/
String getRing();
@ -648,7 +804,18 @@ public interface LinphoneCore {
void setRootCA(String path);
void setUploadBandwidth(int bw);
/**
* Sets maximum available download bandwidth
*
*
* This is IP bandwidth, in kbit/s.
* This information is used signaled to other parties during
* calls (within SDP messages) so that the remote end can have
* sufficient knowledge to properly configure its audio & video
* codec output bitrate to not overflow available bandwidth.
*
* @param bw the bandwidth in kbits/s, 0 for infinite
*/
void setDownloadBandwidth(int bw);
/**
@ -662,9 +829,20 @@ public interface LinphoneCore {
* @param ptime packetization interval in milliseconds
*/
void setUploadPtime(int ptime);
/**
* Sets the preferred video size.
*
* This applies only to the stream that is captured and sent to the remote party,
* since we accept all standard video size on the receive path.
* @param vSize
*
**/
void setPreferredVideoSize(VideoSize vSize);
/**
* get current preferred video size for sending.
* @return video size
*
**/
VideoSize getPreferredVideoSize();
/**
@ -694,6 +872,12 @@ public interface LinphoneCore {
**/
void startEchoCalibration(Object data) throws LinphoneCoreException;
/**
* Returns true if echo calibration is recommended.
* If the device has a builtin echo canceller or calibration value is already known, it will return false.
*/
boolean needsEchoCalibration();
void enableIpv6(boolean enable);
/**
* @deprecated
@ -701,36 +885,159 @@ public interface LinphoneCore {
*/
void adjustSoftwareVolume(int i);
/**
* Pauses a call. If a music file has been setup using {@link LinphoneCore#setPlayFile(String)},
* this file will be played to the remote user.
*
**/
boolean pauseCall(LinphoneCall call);
/**
* Resume a call.
**/
boolean resumeCall(LinphoneCall call);
/**
* Pause all currently running calls.
**/
boolean pauseAllCalls();
void setZrtpSecretsCache(String file);
void enableEchoLimiter(boolean val);
/**
* Indicates whether the local user is part of the conference.
**/
boolean isInConference();
/**
* Moves the local participant inside the conference.
*
* Makes the local participant to join the conference.
* Typically, the local participant is by default always part of the conference when joining an active call into a conference.
* However, by calling {@link #leaveConference()} and {@link #enterConference()} the application can decide to temporarily
* move out and in the local participant from the conference.
*
* @returns true if successful
**/
boolean enterConference();
/**
* Moves the local participant out of the conference.
* When the local participant is out of the conference, the remote participants can continue to talk normally.
**/
void leaveConference();
/**
* Merge a call into a conference.
*
* If this is the first call that enters the conference, the virtual conference will be created automatically.
* If the local user was actively part of the call (ie not in paused state), then the local user is automatically entered into the conference.
* If the call was in paused state, then it is automatically resumed when entering into the conference.
* @param call an established call, either in {@link LinphoneCall.State#StreamsRunning} or {@link LinphoneCall.State#Paused} state.
*
**/
void addToConference(LinphoneCall call);
void addAllToConference();
/**
* Remove a call from the conference.
* @param call a call that has been previously merged into the conference.
*
* After removing the remote participant belonging to the supplied call, the call becomes a normal call in paused state.
* If one single remote participant is left alone together with the local user in the conference after the removal, then the conference is
* automatically transformed into a simple call in StreamsRunning state.
* The conference's resources are then automatically destroyed.
*
* In other words, unless {@link #leaveConference()} is explicitely called, the last remote participant of a conference is automatically
* put in a simple call in running state.
*
**/
void removeFromConference(LinphoneCall call);
void terminateConference();
int getConferenceSize();
/**
* Add all calls into a conference.
*
* Merge all established calls (either in {@link LinphoneCall.State#StreamsRunning} or {@link LinphoneCall.State#Paused}) into a conference.
*
**/
void addAllToConference();
/**
* Terminates the conference and the calls associated with it.
*
* All the calls that were merged to the conference are terminated, and the conference resources are destroyed.
*
**/
void terminateConference();
/**
* Returns the number of participants to the conference, including the local participant.
*
* Typically, after merging two calls into the conference, there is total of 3 participants:
* the local participant (or local user), and two remote participants that were the destinations of the two previously establised calls.
*
* @returns the number of participants to the conference
**/
int getConferenceSize();
/**
* Request recording of the conference into a supplied file path.
* The format is wav.
* @param path where to write recording file
**/
void startConferenceRecording(String path);
/**
* Stop recording of the conference.
**/
void stopConferenceRecording();
/**
* Terminates all the calls.
*/
void terminateAllCalls();
/**
* Returns all calls.
* @return an array with all call currently handle by Linphone core
**/
LinphoneCall[] getCalls();
/**
* Get number of calls currently handled by Linphone core
* @returns number of calls
* */
int getCallsNb();
/**
* Performs a simple call transfer to the specified destination.
*
* @param call The current local call remains active and thus can be later paused or terminated.
* @param referTo The remote call party endpoint is expected to issue a new call to this specified destination.
**/
void transferCall(LinphoneCall call, String referTo);
/**
* Transfer a call to destination of another running call. This is used for "attended transfer" scenarios.
* The transfered call is supposed to be in paused state, so that it is able to accept the transfer immediately.
* The destination call is a call previously established to introduce the transfered person.
* This method will send a transfer request to the transfered person. The phone of the transfered is then
* expected to automatically call to the destination of the transfer. The receiver of the transfer will then automatically
* close the call with us (the 'dest' call).
* @param call a running call you want to transfer
* @param dest a running call whose remote person will receive the transfer
**/
void transferCallToAnother(LinphoneCall callToTransfer, LinphoneCall destination);
/**
* Search from the list of current calls if a remote address match uri
* @param uri which should match call remote uri
* @return LinphoneCall or NULL is no match is found
*/
LinphoneCall findCallFromUri(String uri);
/**
* Get the maximum number of simultaneous calls Linphone core can manage at a time. All new call above this limit are declined with a busy answer
* @return max number of simultaneous calls
*/
int getMaxCalls();
/**
* Set the maximum number of simultaneous calls Linphone core can manage at a time. All new call above this limit are declined with a busy answer
* @param max number of simultaneous calls
*/
void setMaxCalls(int max);
/**
* @deprecated
* @param uri
* @return
*/
boolean isMyself(String uri);
/**
@ -782,15 +1089,31 @@ public interface LinphoneCore {
void tunnelAddServerAndMirror(String host, int port, int udpMirrorPort, int roundTripDelay);
boolean isTunnelAvailable();
/**
* Returns an unmodifiable list of entered proxy configurations.
* @return list of proxy config
**/
LinphoneProxyConfig[] getProxyConfigList();
/**
* Sets the default policy for video.
* This policy defines whether:
* @param autoInitiate video shall be initiated by default for outgoing calls
* @param autoAccept video shall be accepter by default for incoming calls
**/
void setVideoPolicy(boolean autoInitiate, boolean autoAccept);
/** Set static picture to be used when "Static picture" is the video device
* @param path to the static picture file
* */
void setStaticPicture(String path);
/**
* Sets the user agent string used in SIP messages.
* @param user agent name
* @param user agent version
**/
void setUserAgent(String name, String version);
/**
* Set the number of cores used for media processing
* */
void setCpuCount(int count);
/**
@ -837,6 +1160,19 @@ public interface LinphoneCore {
*/
void setAudioPortRange(int minPort, int maxPort);
/**
* Assign a DSCP value to the audio RTP sockets.
* @param dscp the DSCP value.
* DSCP is an IP header field used to indicate a type of service to routers.
*/
void setAudioDscp(int dscp);
/**
* Return DSCP value used for the audio RTP sockets.
* @return the DSCP value used for the audio RTP sockets.
*/
int getAudioDscp();
/**
* Sets the UDP port used for video streaming.
**/
@ -847,6 +1183,19 @@ public interface LinphoneCore {
*/
void setVideoPortRange(int minPort, int maxPort);
/**
* Assign a DSCP value to the video RTP sockets.
* @param dscp the DSCP value.
* DSCP is an IP header field used to indicate a type of service to routers.
*/
void setVideoDscp(int dscp);
/**
* Return DSCP value used for the video RTP sockets.
* @return the DSCP value used for the video RTP sockets.
*/
int getVideoDscp();
/**
* Set the incoming call timeout in seconds.
* If an incoming call isn't answered for this timeout period, it is
@ -859,7 +1208,10 @@ public interface LinphoneCore {
* Once this time is elapsed (ringing included), the call is automatically hung up.
**/
void setInCallTimeout(int timeout);
/**
* Allow to control microphone level:
* @param gain in db
**/
void setMicrophoneGain(float gain);
/**
@ -882,4 +1234,30 @@ public interface LinphoneCore {
* the config file with your own sections
*/
LpConfig getConfig();
/**
* Return the availability of uPnP.
*
* @return true if uPnP is available otherwise return false.
*/
public boolean upnpAvailable();
/**
* Return the internal state of uPnP.
*
* @return an UpnpState.
*/
public UpnpState getUpnpState();
/**
* Return the external ip address of router.
* In some cases the uPnP can have an external ip address but not a usable uPnP
* (state different of Ok).
*
* @return a null terminated string containing the external ip address. If the
* the external ip address is not available return null.
*/
public String getUpnpExternalIpaddress();
}

View file

@ -48,11 +48,27 @@ abstract public class LinphoneCoreFactory {
}
return theLinphoneCoreFactory;
}
/**
* create {@link LinphoneAuthInfo}
* @param username
* @param userid user id as set in auth header
* @param passwd
* */
abstract public LinphoneAuthInfo createAuthInfo(String username,String password, String realm);
/**
* create {@link LinphoneAuthInfo}
* @param username
* @param userid user id as set in auth header
* @param passwd
* @param ha1
* @param realm
* */
abstract public LinphoneAuthInfo createAuthInfo(String username, String userid, String passwd, String ha1,String realm);
abstract public LinphoneCore createLinphoneCore(LinphoneCoreListener listener, String userConfig,String factoryConfig,Object userdata) throws LinphoneCoreException;
abstract public LinphoneCore createLinphoneCore(LinphoneCoreListener listener) throws LinphoneCoreException;
/**
* Constructs a LinphoneAddress object
* @param username
@ -67,6 +83,7 @@ abstract public class LinphoneCoreFactory {
* @return
*/
abstract public LinphoneAddress createLinphoneAddress(String address);
abstract public LpConfig createLpConfig(String file);
abstract public LinphoneProxyConfig createProxyConfig(String identity, String proxy,String route,boolean enableRegister) throws LinphoneCoreException;
/**

View file

@ -45,4 +45,9 @@ public interface LpConfig {
* @param key
*/
void setInt(String section, String key, int value);
/**
* Synchronize LpConfig with file
*/
void sync();
}

View file

@ -0,0 +1,56 @@
package org.linphone.core;
import java.util.Vector;
public class Reason {
static private Vector<Reason> values = new Vector<Reason>();
/**
* None (no failure)
*/
static public Reason None = new Reason(0,"None");
/**
* No response
*/
static public Reason NoResponse = new Reason(1,"NoResponse");
/**
* Bad credentials
*/
static public Reason BadCredentials = new Reason(2,"BadCredentials");
/**
* Call declined
*/
static public Reason Declined = new Reason(3,"Declined");
/**
* Not found
*/
static public Reason NotFound = new Reason(4,"NotFound");
/**
* Call not answered (in time).
*/
static public Reason NotAnswered = new Reason(5,"NotAnswered");
/**
* Call not answered (in time).
*/
static public Reason Busy = new Reason(6,"Busy");
protected final int mValue;
private final String mStringValue;
private Reason(int value,String stringValue) {
mValue = value;
values.addElement(this);
mStringValue=stringValue;
}
public static Reason fromInt(int value) {
for (int i=0; i<values.size();i++) {
Reason state = (Reason) values.elementAt(i);
if (state.mValue == value) return state;
}
throw new RuntimeException("Reason not found ["+value+"]");
}
public String toString() {
return mStringValue;
}
}

View file

@ -31,6 +31,7 @@ public class LinphoneAddressImpl implements LinphoneAddress {
private native String toUri(long ptr);
private native void setDisplayName(long ptr,String name);
private native String toString(long ptr);
private native void setDomain(long ptr, String domain);
protected LinphoneAddressImpl(String identity) {
nativePtr = newLinphoneAddressImpl(identity, null);
@ -85,7 +86,7 @@ public class LinphoneAddressImpl implements LinphoneAddress {
return getPortInt();
}
public void setDomain(String domain) {
throw new RuntimeException("Not implemented");
setDomain(nativePtr, domain);
}
public void setPort(String port) {
throw new RuntimeException("Not implemented");

View file

@ -20,36 +20,66 @@ package org.linphone.core;
class LinphoneAuthInfoImpl implements LinphoneAuthInfo {
protected final long nativePtr;
private native long newLinphoneAuthInfo(String username, String userid, String passwd, String ha1,String realm);
private native long newLinphoneAuthInfo();
private native void delete(long ptr);
private native String getPassword(long ptr);
private native String getRealm(long ptr);
private native String getUsername(long ptr);
private native void setPassword(long ptr, String password);
private native void setRealm(long ptr, String realm);
private native void setUsername(long ptr, String username);
private native void setUserId(long ptr, String username);
private native void setHa1(long ptr, String ha1);
private native String getUserId(long ptr);
private native String getHa1(long ptr);
protected LinphoneAuthInfoImpl(String username,String password, String realm) {
nativePtr = newLinphoneAuthInfo(username,"",password,"","");
this(username,null,password,null,null);
}
protected LinphoneAuthInfoImpl(String username, String userid, String passwd, String ha1,String realm) {
nativePtr = newLinphoneAuthInfo();
this.setUsername(username);
this.setUserId(userid);
this.setPassword(passwd);
this.setHa1(ha1);
}
protected void finalize() throws Throwable {
delete(nativePtr);
}
public String getPassword() {
// TODO Auto-generated method stub
throw new RuntimeException("not implemeneted yet");
return getPassword (nativePtr);
}
public String getRealm() {
// TODO Auto-generated method stub
throw new RuntimeException("not implemeneted yet");
return getRealm (nativePtr);
}
public String getUsername() {
// TODO Auto-generated method stub
throw new RuntimeException("not implemeneted yet");
return getUsername (nativePtr);
}
public void setPassword(String password) {
// TODO Auto-generated method stub
throw new RuntimeException("not implemeneted yet");
setPassword(nativePtr,password);
}
public void setRealm(String realm) {
// TODO Auto-generated method stub
throw new RuntimeException("not implemeneted yet");
setRealm(nativePtr,realm);
}
public void setUsername(String username) {
// TODO Auto-generated method stub
throw new RuntimeException("not implemeneted yet");
setUsername(nativePtr,username);
}
@Override
public String getUserId() {
return getUserId(nativePtr);
}
@Override
public void setUserId(String userid) {
setUserId(nativePtr,userid);
}
@Override
public String getHa1() {
return getHa1(nativePtr);
}
@Override
public void setHa1(String ha1) {
setHa1(nativePtr,ha1);
}
}

View file

@ -68,9 +68,11 @@ class LinphoneCallImpl implements LinphoneCall {
videoStats = stats;
}
public LinphoneCallStats getAudioStats() {
if (audioStats!=null) ((LinphoneCallStatsImpl)audioStats).updateRealTimeStats(this);
return audioStats;
}
public LinphoneCallStats getVideoStats() {
if (videoStats!=null) ((LinphoneCallStatsImpl)videoStats).updateRealTimeStats(this);
return videoStats;
}
public CallDirection getDirection() {
@ -179,6 +181,11 @@ class LinphoneCallImpl implements LinphoneCall {
public String getRemoteUserAgent() {
return getRemoteUserAgent(nativePtr);
}
private native String getRemoteContact(long nativePtr);
public String getRemoteContact() {
return getRemoteContact(nativePtr);
}
private native void takeSnapshot(long nativePtr, String path);
public void takeSnapshot(String path) {
@ -189,4 +196,15 @@ class LinphoneCallImpl implements LinphoneCall {
public void zoomVideo(float factor, float cx, float cy) {
zoomVideo(nativePtr, factor, cx, cy);
}
private native void startRecording(long nativePtr);
@Override
public void startRecording() {
startRecording(nativePtr);
}
private native void stopRecording(long nativePtr);
@Override
public void stopRecording() {
stopRecording(nativePtr);
}
}

View file

@ -88,4 +88,23 @@ public class LinphoneCallParamsImpl implements LinphoneCallParams {
public boolean isLowBandwidthEnabled() {
return isLowBandwidthEnabled(nativePtr);
}
private native void setRecordFile(long nativePtr, String path);
@Override
public void setRecordFile(String path) {
setRecordFile(nativePtr,path);
}
private native void addCustomHeader(long nativePtr, String name, String value);
@Override
public void addCustomHeader(String name, String value) {
addCustomHeader(nativePtr,name,value);
}
private native String getCustomHeader(long nativePtr, String name);
@Override
public String getCustomHeader(String name) {
return getCustomHeader(nativePtr,name);
}
}

View file

@ -31,6 +31,9 @@ class LinphoneCallStatsImpl implements LinphoneCallStats {
private float roundTripDelay;
private long latePacketsCumulativeNumber;
private float jitterBufferSize;
private float localLossRate;
private float localLateRate;
private long nativePtr;
private native int getMediaType(long nativeStatsPtr);
private native int getIceState(long nativeStatsPtr);
@ -43,8 +46,12 @@ class LinphoneCallStatsImpl implements LinphoneCallStats {
private native float getRoundTripDelay(long nativeStatsPtr);
private native long getLatePacketsCumulativeNumber(long nativeStatsPtr, long nativeCallPtr);
private native float getJitterBufferSize(long nativeStatsPtr);
private native float getLocalLossRate(long nativeStatsPtr);
private native float getLocalLateRate(long nativeStatsPtr);
private native void updateStats(long nativeCallPtr, int mediaType);
protected LinphoneCallStatsImpl(long nativeCallPtr, long nativeStatsPtr) {
nativePtr=nativeStatsPtr;
mediaType = getMediaType(nativeStatsPtr);
iceState = getIceState(nativeStatsPtr);
downloadBandwidth = getDownloadBandwidth(nativeStatsPtr);
@ -56,6 +63,13 @@ class LinphoneCallStatsImpl implements LinphoneCallStats {
roundTripDelay = getRoundTripDelay(nativeStatsPtr);
latePacketsCumulativeNumber = getLatePacketsCumulativeNumber(nativeStatsPtr, nativeCallPtr);
jitterBufferSize = getJitterBufferSize(nativeStatsPtr);
}
protected void updateRealTimeStats(LinphoneCall call){
updateStats( ((LinphoneCallImpl)call).nativePtr, mediaType);
localLossRate=getLocalLossRate(nativePtr);
localLateRate=getLocalLateRate(nativePtr);
}
public MediaType getMediaType() {
@ -101,4 +115,12 @@ class LinphoneCallStatsImpl implements LinphoneCallStats {
public float getJitterBufferSize() {
return jitterBufferSize;
}
public float getLocalLossRate(){
return localLossRate;
}
public float getLocalLateRate(){
return localLateRate;
}
}

View file

@ -3,11 +3,12 @@ package org.linphone.core;
public class LinphoneChatMessageImpl implements LinphoneChatMessage {
protected final long nativePtr;
private native void setUserData(long ptr);
private native String getMessage(long ptr);
private native String getText(long ptr);
private native long getPeerAddress(long ptr);
private native String getExternalBodyUrl(long ptr);
private native void setExternalBodyUrl(long ptr, String url);
private native long getFrom(long ptr);
private native long getTime(long ptr);
protected LinphoneChatMessageImpl(long aNativePtr) {
nativePtr = aNativePtr;
@ -30,8 +31,8 @@ public class LinphoneChatMessageImpl implements LinphoneChatMessage {
}
@Override
public String getMessage() {
return getMessage(nativePtr);
public String getText() {
return getText(nativePtr);
}
@Override
@ -53,4 +54,19 @@ public class LinphoneChatMessageImpl implements LinphoneChatMessage {
public LinphoneAddress getFrom() {
return new LinphoneAddressImpl(getFrom(nativePtr));
}
private native void addCustomHeader(long nativePtr, String name, String value);
@Override
public void addCustomHeader(String name, String value) {
addCustomHeader(nativePtr, name, value);
}
private native String getCustomHeader(long nativePtr, String name);
@Override
public String getCustomHeader(String name) {
return getCustomHeader(nativePtr,name);
}
public long getTime() {
return getTime(nativePtr) * 1000; // Need milliseconds, not seconds
}
}

View file

@ -20,8 +20,8 @@ package org.linphone.core;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import org.linphone.mediastream.CpuUtils;
import org.linphone.mediastream.Version;
import android.util.Log;
@ -43,6 +43,8 @@ public class LinphoneCoreFactoryImpl extends LinphoneCoreFactory {
loadOptionalLibrary("avutil");
loadOptionalLibrary("swscale");
loadOptionalLibrary("avcore");
System.loadLibrary("neon");
if (!hasNeonInCpuFeatures()) {
boolean noNeonLibrariesLoaded = loadOptionalLibrary("avcodecnoneon");
@ -69,20 +71,20 @@ public class LinphoneCoreFactoryImpl extends LinphoneCoreFactory {
loadOptionalLibrary("bcg729");
//Main library
if (!hasNeonInCpuFeatures()) {
try {
if (!isArmv7() && !Version.isX86()) {
System.loadLibrary("linphonearmv5");
} else {
System.loadLibrary("linphonenoneon");
}
Log.w("linphone", "No-neon liblinphone loaded");
} catch (UnsatisfiedLinkError ule) {
Log.w("linphone", "Failed to load no-neon liblinphone, loading neon liblinphone");
System.loadLibrary("linphone");
if (isArmv7()) {
if (hasNeonInCpuFeatures()) {
Log.d("linphone", "armv7 liblinphone loaded");
System.loadLibrary("linphonearmv7");
} else {
Log.w("linphone", "No-neon armv7 liblinphone loaded");
System.loadLibrary("linphonearmv7noneon");
}
} else if (Version.isX86()) {
Log.d("linphone", "No-neon x86 liblinphone loaded");
System.loadLibrary("linphonex86");
} else {
System.loadLibrary("linphone");
Log.d("linphone", "No-neon armv5 liblinphone loaded");
System.loadLibrary("linphonearmv5noneon");
}
Version.dumpCapabilities();
@ -103,6 +105,11 @@ public class LinphoneCoreFactoryImpl extends LinphoneCoreFactory {
public LinphoneAddress createLinphoneAddress(String identity) {
return new LinphoneAddressImpl(identity);
}
@Override
public LpConfig createLpConfig(String file) {
return new LpConfigImpl(file);
}
@Override
public LinphoneCore createLinphoneCore(LinphoneCoreListener listener,
@ -151,32 +158,18 @@ public class LinphoneCoreFactoryImpl extends LinphoneCoreFactory {
public static boolean hasNeonInCpuFeatures()
{
ProcessBuilder cmd;
boolean result = false;
try {
String[] args = {"/system/bin/cat", "/proc/cpuinfo"};
cmd = new ProcessBuilder(args);
Process process = cmd.start();
InputStream in = process.getInputStream();
byte[] re = new byte[1024];
while(in.read(re) != -1){
String line = new String(re);
if (line.contains("Features")) {
result = line.contains("neon");
break;
}
}
in.close();
} catch(IOException ex){
ex.printStackTrace();
}
return result;
CpuUtils cpu = new CpuUtils();
return cpu.isCpuNeon();
}
public static boolean isArmv7()
{
return System.getProperty("os.arch").contains("armv7");
}
@Override
public LinphoneAuthInfo createAuthInfo(String username, String userid,
String passwd, String ha1, String realm) {
return new LinphoneAuthInfoImpl(username,userid,passwd,ha1,realm);
}
}

View file

@ -745,42 +745,36 @@ class LinphoneCoreImpl implements LinphoneCore {
deferCallUpdate(nativePtr, getCallPtr(aCall));
}
public synchronized void startRinging() {
if (!contextInitialized()) return;
if (Hacks.needGalaxySAudioHack()) {
mAudioManager.setMode(MODE_RINGTONE);
}
}
private native void setVideoPolicy(long nativePtr, boolean autoInitiate, boolean autoAccept);
public synchronized void setVideoPolicy(boolean autoInitiate, boolean autoAccept) {
setVideoPolicy(nativePtr, autoInitiate, autoAccept);
}
private native void setStaticPicture(long nativePtr, String path);
public void setStaticPicture(String path) {
public synchronized void setStaticPicture(String path) {
setStaticPicture(nativePtr, path);
}
private native void setUserAgent(long nativePtr, String name, String version);
@Override
public void setUserAgent(String name, String version) {
public synchronized void setUserAgent(String name, String version) {
setUserAgent(nativePtr,name,version);
}
private native void setCpuCountNative(int count);
public void setCpuCount(int count)
public synchronized void setCpuCount(int count)
{
setCpuCountNative(count);
}
public int getMissedCallsCount() {
public synchronized int getMissedCallsCount() {
return getMissedCallsCount(nativePtr);
}
public void removeCallLog(LinphoneCallLog log) {
public synchronized void removeCallLog(LinphoneCallLog log) {
removeCallLog(nativePtr, ((LinphoneCallLogImpl) log).getNativePtr());
}
public void resetMissedCallsCount() {
public synchronized void resetMissedCallsCount() {
resetMissedCallsCount(nativePtr);
}
@ -793,7 +787,7 @@ class LinphoneCoreImpl implements LinphoneCore {
}
private native void refreshRegisters(long nativePtr);
public void refreshRegisters() {
public synchronized void refreshRegisters() {
refreshRegisters(nativePtr);
}
@ -801,21 +795,28 @@ class LinphoneCoreImpl implements LinphoneCore {
public String getVersion() {
return getVersion(nativePtr);
}
/**
* Wildcard value used by #linphone_core_find_payload_type to ignore rate in search algorithm
*/
static int FIND_PAYLOAD_IGNORE_RATE = -1;
/**
* Wildcard value used by #linphone_core_find_payload_type to ignore channel in search algorithm
*/
static int FIND_PAYLOAD_IGNORE_CHANNELS = -1;
@Override
public PayloadType findPayloadType(String mime, int clockRate) {
return findPayloadType(mime, clockRate, 1);
public synchronized PayloadType findPayloadType(String mime, int clockRate) {
return findPayloadType(mime, clockRate, FIND_PAYLOAD_IGNORE_CHANNELS);
}
private native void removeFriend(long ptr, long lf);
@Override
public void removeFriend(LinphoneFriend lf) {
public synchronized void removeFriend(LinphoneFriend lf) {
removeFriend(nativePtr, lf.getNativePtr());
}
private native long getFriendByAddress(long ptr, String sipUri);
@Override
public LinphoneFriend findFriendByAddress(String sipUri) {
public synchronized LinphoneFriend findFriendByAddress(String sipUri) {
long ptr = getFriendByAddress(nativePtr, sipUri);
if (ptr == 0) {
return null;
@ -823,53 +824,128 @@ class LinphoneCoreImpl implements LinphoneCore {
return new LinphoneFriendImpl(ptr);
}
public void setAudioPort(int port) {
public synchronized void setAudioPort(int port) {
setAudioPort(nativePtr, port);
}
public void setVideoPort(int port) {
public synchronized void setVideoPort(int port) {
setVideoPort(nativePtr, port);
}
public void setAudioPortRange(int minPort, int maxPort) {
public synchronized void setAudioPortRange(int minPort, int maxPort) {
setAudioPortRange(nativePtr, minPort, maxPort);
}
public void setVideoPortRange(int minPort, int maxPort) {
public synchronized void setVideoPortRange(int minPort, int maxPort) {
setVideoPortRange(nativePtr, minPort, maxPort);
}
public void setIncomingTimeout(int timeout) {
public synchronized void setIncomingTimeout(int timeout) {
setIncomingTimeout(nativePtr, timeout);
}
public void setInCallTimeout(int timeout)
public synchronized void setInCallTimeout(int timeout)
{
setInCallTimeout(nativePtr, timeout);
}
private native void setMicrophoneGain(long ptr, float gain);
public void setMicrophoneGain(float gain) {
public synchronized void setMicrophoneGain(float gain) {
setMicrophoneGain(nativePtr, gain);
}
public void setPrimaryContact(String displayName, String username) {
public synchronized void setPrimaryContact(String displayName, String username) {
setPrimaryContact(nativePtr, displayName, username);
}
private native void setUseSipInfoForDtmfs(long ptr, boolean use);
public void setUseSipInfoForDtmfs(boolean use) {
public synchronized void setUseSipInfoForDtmfs(boolean use) {
setUseSipInfoForDtmfs(nativePtr, use);
}
private native void setUseRfc2833ForDtmfs(long ptr, boolean use);
public void setUseRfc2833ForDtmfs(boolean use) {
public synchronized void setUseRfc2833ForDtmfs(boolean use) {
setUseRfc2833ForDtmfs(nativePtr, use);
}
private native long getConfig(long ptr);
public LpConfig getConfig() {
public synchronized LpConfig getConfig() {
long configPtr=getConfig(nativePtr);
return new LpConfigImpl(configPtr);
}
private native boolean needsEchoCalibration(long ptr);
@Override
public synchronized boolean needsEchoCalibration() {
return needsEchoCalibration(nativePtr);
}
private native void declineCall(long coreptr, long callptr, int reason);
@Override
public synchronized void declineCall(LinphoneCall aCall, Reason reason) {
declineCall(nativePtr,((LinphoneCallImpl)aCall).nativePtr,reason.mValue);
}
private native boolean upnpAvailable(long ptr);
public boolean upnpAvailable() {
return upnpAvailable(nativePtr);
}
private native int getUpnpState(long ptr);
public UpnpState getUpnpState() {
return UpnpState.fromInt(getUpnpState(nativePtr));
}
private native String getUpnpExternalIpaddress(long ptr);
public String getUpnpExternalIpaddress() {
return getUpnpExternalIpaddress(nativePtr);
}
private native int startConferenceRecording(long nativePtr, String path);
@Override
public void startConferenceRecording(String path) {
startConferenceRecording(nativePtr,path);
}
private native int stopConferenceRecording(long nativePtr);
@Override
public void stopConferenceRecording() {
stopConferenceRecording(nativePtr);
}
@Override
public PayloadType findPayloadType(String mime) {
return findPayloadType(mime, FIND_PAYLOAD_IGNORE_RATE);
}
private native void setSipDscp(long nativePtr, int dscp);
@Override
public void setSipDscp(int dscp) {
setSipDscp(nativePtr,dscp);
}
private native int getSipDscp(long nativePtr);
@Override
public int getSipDscp() {
return getSipDscp(nativePtr);
}
private native void setAudioDscp(long nativePtr, int dscp);
@Override
public void setAudioDscp(int dscp) {
setAudioDscp(nativePtr, dscp);
}
private native int getAudioDscp(long nativePtr);
@Override
public int getAudioDscp() {
return getAudioDscp(nativePtr);
}
private native void setVideoDscp(long nativePtr, int dscp);
@Override
public void setVideoDscp(int dscp) {
setVideoDscp(nativePtr,dscp);
}
private native int getVideoDscp(long nativePtr);
@Override
public int getVideoDscp() {
return getVideoDscp(nativePtr);
}
}

View file

@ -23,10 +23,28 @@ package org.linphone.core;
class LpConfigImpl implements LpConfig {
private final long nativePtr;
boolean ownPtr = false;
public LpConfigImpl(long ptr) {
nativePtr=ptr;
}
private native long newLpConfigImpl(String file);
private native void delete(long ptr);
public LpConfigImpl(String file) {
nativePtr = newLpConfigImpl(file);
ownPtr = true;
}
protected void finalize() throws Throwable {
if(ownPtr) {
delete(nativePtr);
}
}
private native void sync(long ptr);
public void sync() {
sync(nativePtr);
}
private native void setInt(long ptr, String section, String key, int value);
public void setInt(String section, String key, int value) {

View file

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

View file

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

View file

@ -14,3 +14,5 @@
./bin/libgpg-error-0.dll
./bin/libgnutls-26.dll
./bin/libtasn1-3.dll
./bin/libsqlite3-0.dll
./bin/libzrtpcpp.dll

View file

@ -1,558 +0,0 @@
<?xml version = '1.0'?>
<kdevelop>
<general>
<author>Simon Morlat</author>
<email>simon.morlat@linphone.org</email>
<version>[3.1.2]</version>
<projectmanagement>KDevCustomProject</projectmanagement>
<primarylanguage>C</primarylanguage>
<ignoreparts/>
<projectname>linphone</projectname>
<projectdirectory>.</projectdirectory>
<absoluteprojectpath>false</absoluteprojectpath>
<description/>
<defaultencoding/>
</general>
<kdevcustomproject>
<run>
<directoryradio>executable</directoryradio>
<mainprogram>gtk-glade/linphone</mainprogram>
<programargs/>
<globaldebugarguments/>
<globalcwd/>
<useglobalprogram>false</useglobalprogram>
<terminal>false</terminal>
<autocompile>false</autocompile>
<autoinstall>false</autoinstall>
<autokdesu>false</autokdesu>
<envvars/>
</run>
<filetypes>
<filetype>*.java</filetype>
<filetype>*.h</filetype>
<filetype>*.H</filetype>
<filetype>*.hh</filetype>
<filetype>*.hxx</filetype>
<filetype>*.hpp</filetype>
<filetype>*.c</filetype>
<filetype>*.C</filetype>
<filetype>*.cc</filetype>
<filetype>*.cpp</filetype>
<filetype>*.c++</filetype>
<filetype>*.cxx</filetype>
</filetypes>
<blacklist>
<path>config.h</path>
<path>exosip</path>
<path>exosip/eXosip2.h</path>
<path>exosip/eXosip.c</path>
<path>exosip/eXosip_cfg.h</path>
<path>exosip/eXosip.h</path>
<path>exosip/eXutils.c</path>
<path>exosip/jauth.c</path>
<path>exosip/jcallback.c</path>
<path>exosip/jcall.c</path>
<path>exosip/jdialog.c</path>
<path>exosip/jevents.c</path>
<path>exosip/jfreinds.c</path>
<path>exosip/jidentity.c</path>
<path>exosip/jnotify.c</path>
<path>exosip/jpipe.c</path>
<path>exosip/jpipe.h</path>
<path>exosip/jpublish.c</path>
<path>exosip/jreg.c</path>
<path>exosip/jrequest.c</path>
<path>exosip/jresponse.c</path>
<path>exosip/jsubscribe.c</path>
<path>exosip/jsubscribers.c</path>
<path>exosip/misc.c</path>
<path>exosip/sdp_offans.c</path>
<path>exosip/udp.c</path>
<path>gnome</path>
<path>gnome/addressbook.c</path>
<path>gnome/addressbook.h</path>
<path>gnome/applet.c</path>
<path>gnome/callbacks.c</path>
<path>gnome/callbacks.h</path>
<path>gnome/friends.c</path>
<path>gnome/friends.h</path>
<path>gnome/gui_utils.c</path>
<path>gnome/gui_utils.h</path>
<path>gnome/interface.c</path>
<path>gnome/interface.h</path>
<path>gnome/linphone.c</path>
<path>gnome/linphone.h</path>
<path>gnome/main.c</path>
<path>gnome/presence.c</path>
<path>gnome/presence.h</path>
<path>gnome/propertybox.c</path>
<path>gnome/propertybox.h</path>
<path>gnome/support.c</path>
<path>gnome/support.h</path>
<path>gsmlib</path>
<path>gsmlib/code.c</path>
<path>gsmlib/config.h</path>
<path>gsmlib/debug.c</path>
<path>gsmlib/decode.c</path>
<path>gsmlib/gsmadd.c</path>
<path>gsmlib/gsm_create.c</path>
<path>gsmlib/gsm_decode.c</path>
<path>gsmlib/gsm_destroy.c</path>
<path>gsmlib/gsm_encode.c</path>
<path>gsmlib/gsm_explode.c</path>
<path>gsmlib/gsm.h</path>
<path>gsmlib/gsm_implode.c</path>
<path>gsmlib/gsm_option.c</path>
<path>gsmlib/gsm_print.c</path>
<path>gsmlib/gsm_wrapper.c</path>
<path>gsmlib/gsm_wrapper.h</path>
<path>gsmlib/long_term.c</path>
<path>gsmlib/lpc.c</path>
<path>gsmlib/preprocess.c</path>
<path>gsmlib/private.h</path>
<path>gsmlib/proto.h</path>
<path>gsmlib/rpe.c</path>
<path>gsmlib/short_term.c</path>
<path>gsmlib/table.c</path>
<path>gsmlib/toast.h</path>
<path>gsmlib/unproto.h</path>
<path>gtk</path>
<path>gtk/addressbook.c</path>
<path>gtk/addressbook.h</path>
<path>gtk/applet.c</path>
<path>gtk/callbacks.c</path>
<path>gtk/callbacks.h</path>
<path>gtk/friends.c</path>
<path>gtk/friends.h</path>
<path>gtk/gui_utils.c</path>
<path>gtk/gui_utils.h</path>
<path>gtk/interface.c</path>
<path>gtk/interface.h</path>
<path>gtk/linphone.c</path>
<path>gtk/linphone.h</path>
<path>gtk/main.c</path>
<path>gtk/presence.c</path>
<path>gtk/presence.h</path>
<path>gtk/propertybox.c</path>
<path>gtk/propertybox.h</path>
<path>gtk/support.c</path>
<path>gtk/support.h</path>
<path>intl</path>
<path>intl/bindtextdom.c</path>
<path>intl/cat-compat.c</path>
<path>intl/dcgettext.c</path>
<path>intl/dgettext.c</path>
<path>intl/explodename.c</path>
<path>intl/finddomain.c</path>
<path>intl/gettext.c</path>
<path>intl/gettext.h</path>
<path>intl/gettextP.h</path>
<path>intl/hash-string.h</path>
<path>intl/intl-compat.c</path>
<path>intl/l10nflist.c</path>
<path>intl/libgettext.h</path>
<path>intl/loadinfo.h</path>
<path>intl/loadmsgcat.c</path>
<path>intl/localealias.c</path>
<path>intl/textdomain.c</path>
<path>lpc10-1.5</path>
<path>lpc10-1.5/analys.c</path>
<path>lpc10-1.5/bitio.c</path>
<path>lpc10-1.5/bsynz.c</path>
<path>lpc10-1.5/chanwr.c</path>
<path>lpc10-1.5/dcbias.c</path>
<path>lpc10-1.5/decode.c</path>
<path>lpc10-1.5/deemp.c</path>
<path>lpc10-1.5/difmag.c</path>
<path>lpc10-1.5/dyptrk.c</path>
<path>lpc10-1.5/encode.c</path>
<path>lpc10-1.5/energy.c</path>
<path>lpc10-1.5/f2c.h</path>
<path>lpc10-1.5/f2clib.c</path>
<path>lpc10-1.5/ham84.c</path>
<path>lpc10-1.5/hp100.c</path>
<path>lpc10-1.5/invert.c</path>
<path>lpc10-1.5/irc2pc.c</path>
<path>lpc10-1.5/ivfilt.c</path>
<path>lpc10-1.5/lpc10.h</path>
<path>lpc10-1.5/lpc10_wrapper.c</path>
<path>lpc10-1.5/lpc10_wrapper.h</path>
<path>lpc10-1.5/lpcdec.c</path>
<path>lpc10-1.5/lpcenc.c</path>
<path>lpc10-1.5/lpcini.c</path>
<path>lpc10-1.5/lpfilt.c</path>
<path>lpc10-1.5/median.c</path>
<path>lpc10-1.5/mload.c</path>
<path>lpc10-1.5/onset.c</path>
<path>lpc10-1.5/pitsyn.c</path>
<path>lpc10-1.5/placea.c</path>
<path>lpc10-1.5/placev.c</path>
<path>lpc10-1.5/preemp.c</path>
<path>lpc10-1.5/prepro.c</path>
<path>lpc10-1.5/random.c</path>
<path>lpc10-1.5/rcchk.c</path>
<path>lpc10-1.5/synths.c</path>
<path>lpc10-1.5/tbdm.c</path>
<path>lpc10-1.5/voicin.c</path>
<path>lpc10-1.5/vparms.c</path>
<path>media_api</path>
<path>media_api/apitest.c</path>
<path>media_api/apitest.h</path>
<path>media_api/basiccall.c</path>
<path>media_api/basiccall.h</path>
<path>media_api/callmember.c</path>
<path>media_api/callmember.h</path>
<path>media_api/common.h</path>
<path>media_api/media_api.c</path>
<path>media_api/media_api.h</path>
<path>media_api/mediaflow.c</path>
<path>media_api/mediaflow.h</path>
<path>mediastreamer</path>
<path>mediastreamer/affine.c</path>
<path>mediastreamer/affine.h</path>
<path>mediastreamer/alsacard.c</path>
<path>mediastreamer/alsacard.h</path>
<path>mediastreamer/audiostream.c</path>
<path>mediastreamer/g711common.h</path>
<path>mediastreamer/hpuxsndcard.c</path>
<path>mediastreamer/jackcard.c</path>
<path>mediastreamer/jackcard.h</path>
<path>mediastreamer/mediastream.c</path>
<path>mediastreamer/mediastream.h</path>
<path>mediastreamer/msAlawdec.c</path>
<path>mediastreamer/msAlawdec.h</path>
<path>mediastreamer/msAlawenc.c</path>
<path>mediastreamer/msAlawenc.h</path>
<path>mediastreamer/msavdecoder.c</path>
<path>mediastreamer/msavdecoder.h</path>
<path>mediastreamer/msavencoder.c</path>
<path>mediastreamer/msavencoder.h</path>
<path>mediastreamer/msbuffer.c</path>
<path>mediastreamer/msbuffer.h</path>
<path>mediastreamer/ms.c</path>
<path>mediastreamer/mscodec.c</path>
<path>mediastreamer/mscodec.h</path>
<path>mediastreamer/mscopy.c</path>
<path>mediastreamer/mscopy.h</path>
<path>mediastreamer/msfdispatcher.c</path>
<path>mediastreamer/msfdispatcher.h</path>
<path>mediastreamer/msfifo.c</path>
<path>mediastreamer/msfifo.h</path>
<path>mediastreamer/msfilter.c</path>
<path>mediastreamer/msfilter.h</path>
<path>mediastreamer/msGSMdecoder.c</path>
<path>mediastreamer/msGSMdecoder.h</path>
<path>mediastreamer/msGSMencoder.c</path>
<path>mediastreamer/msGSMencoder.h</path>
<path>mediastreamer/ms.h</path>
<path>mediastreamer/msLPC10decoder.c</path>
<path>mediastreamer/msLPC10decoder.h</path>
<path>mediastreamer/msLPC10encoder.c</path>
<path>mediastreamer/msLPC10encoder.h</path>
<path>mediastreamer/msMUlawdec.c</path>
<path>mediastreamer/msMUlawdec.h</path>
<path>mediastreamer/msMUlawenc.c</path>
<path>mediastreamer/msMUlawenc.h</path>
<path>mediastreamer/msnosync.c</path>
<path>mediastreamer/msnosync.h</path>
<path>mediastreamer/msossread.c</path>
<path>mediastreamer/msossread.h</path>
<path>mediastreamer/msosswrite.c</path>
<path>mediastreamer/msosswrite.h</path>
<path>mediastreamer/msqdispatcher.c</path>
<path>mediastreamer/msqdispatcher.h</path>
<path>mediastreamer/msqueue.c</path>
<path>mediastreamer/msqueue.h</path>
<path>mediastreamer/msread.c</path>
<path>mediastreamer/msread.h</path>
<path>mediastreamer/msringplayer.c</path>
<path>mediastreamer/msringplayer.h</path>
<path>mediastreamer/msrtprecv.c</path>
<path>mediastreamer/msrtprecv.h</path>
<path>mediastreamer/msrtpsend.c</path>
<path>mediastreamer/msrtpsend.h</path>
<path>mediastreamer/mssdlout.c</path>
<path>mediastreamer/mssdlout.h</path>
<path>mediastreamer/mssmpeg.c</path>
<path>mediastreamer/mssmpeg.h</path>
<path>mediastreamer/mssoundread.c</path>
<path>mediastreamer/mssoundread.h</path>
<path>mediastreamer/mssoundwrite.c</path>
<path>mediastreamer/mssoundwrite.h</path>
<path>mediastreamer/msspeexdec.c</path>
<path>mediastreamer/msspeexdec.h</path>
<path>mediastreamer/msspeexenc.c</path>
<path>mediastreamer/msspeexenc.h</path>
<path>mediastreamer/mssync.c</path>
<path>mediastreamer/mssync.h</path>
<path>mediastreamer/mstcpclient.c</path>
<path>mediastreamer/mstcpclient.h</path>
<path>mediastreamer/mstcpserv.c</path>
<path>mediastreamer/mstcpserv.h</path>
<path>mediastreamer/mstimer.c</path>
<path>mediastreamer/mstimer.h</path>
<path>mediastreamer/mstruespeechdecoder.c</path>
<path>mediastreamer/mstruespeechdecoder.h</path>
<path>mediastreamer/mstruespeechencoder.c</path>
<path>mediastreamer/mstruespeechencoder.h</path>
<path>mediastreamer/msutils.h</path>
<path>mediastreamer/msv4l.c</path>
<path>mediastreamer/msv4l.h</path>
<path>mediastreamer/msvideooutput.c</path>
<path>mediastreamer/msvideooutput.h</path>
<path>mediastreamer/msvideosource.c</path>
<path>mediastreamer/msvideosource.h</path>
<path>mediastreamer/mswrite.c</path>
<path>mediastreamer/mswrite.h</path>
<path>mediastreamer/msxine.c</path>
<path>mediastreamer/msxine.h</path>
<path>mediastreamer/osscard.c</path>
<path>mediastreamer/osscard.h</path>
<path>mediastreamer/rfc2429.h</path>
<path>mediastreamer/ring_test.c</path>
<path>mediastreamer/sndcard.c</path>
<path>mediastreamer/sndcard.h</path>
<path>mediastreamer/test_alaw.c</path>
<path>mediastreamer/test.c</path>
<path>mediastreamer/test_gsm.c</path>
<path>mediastreamer/test_lpc10.c</path>
<path>mediastreamer/test_mulaw.c</path>
<path>mediastreamer/test_rtprecv.c</path>
<path>mediastreamer/test_smpeg.c</path>
<path>mediastreamer/test_speex.c</path>
<path>mediastreamer/test_truespeech.c</path>
<path>mediastreamer/test_v4l.c</path>
<path>mediastreamer/test_videostream.c</path>
<path>mediastreamer/test_xine.c</path>
<path>mediastreamer/videoclient.c</path>
<path>mediastreamer/videoserver.c</path>
<path>mediastreamer/videostream.c</path>
<path>mediastreamer/waveheader.h</path>
<path>po</path>
<path>po/cat-id-tbl.c</path>
<path>win32acm</path>
<path>win32acm/afl.c</path>
<path>win32acm/com.h</path>
<path>win32acm/config.h</path>
<path>win32acm/cpudetect.c</path>
<path>win32acm/cpudetect.h</path>
<path>win32acm/cputable.h</path>
<path>win32acm/driver.c</path>
<path>win32acm/driver.h</path>
<path>win32acm/elfdll.c</path>
<path>win32acm/ext.c</path>
<path>win32acm/ext.h</path>
<path>win32acm/ldt_keeper.c</path>
<path>win32acm/ldt_keeper.h</path>
<path>win32acm/loader.h</path>
<path>win32acm/module.c</path>
<path>win32acm/mp_msg.c</path>
<path>win32acm/mp_msg.h</path>
<path>win32acm/pe_image.c</path>
<path>win32acm/pe_resource.c</path>
<path>win32acm/registry.c</path>
<path>win32acm/registry.h</path>
<path>win32acm/resource.c</path>
<path>win32acm/test_truespeech.c</path>
<path>win32acm/win32.c</path>
<path>win32acm/win32codec.c</path>
<path>win32acm/win32codec.h</path>
<path>win32acm/win32.h</path>
<path>win32acm/wine</path>
<path>win32acm/wine/basetsd.h</path>
<path>win32acm/wine/debugtools.h</path>
<path>win32acm/wine/driver.h</path>
<path>win32acm/wine/elfdll.h</path>
<path>win32acm/wine/heap.h</path>
<path>win32acm/wine/ldt.h</path>
<path>win32acm/wine/mmreg.h</path>
<path>win32acm/wine/module.h</path>
<path>win32acm/wine/msacmdrv.h</path>
<path>win32acm/wine/msacm.h</path>
<path>win32acm/wine/ntdef.h</path>
<path>win32acm/wine/pe_image.h</path>
<path>win32acm/wine/poppack.h</path>
<path>win32acm/wine/pshpack1.h</path>
<path>win32acm/wine/pshpack2.h</path>
<path>win32acm/wine/pshpack4.h</path>
<path>win32acm/wine/pshpack8.h</path>
<path>win32acm/wine/vfw.h</path>
<path>win32acm/wine/winbase.h</path>
<path>win32acm/wine/windef.h</path>
<path>win32acm/wine/windows.h</path>
<path>win32acm/wine/winerror.h</path>
<path>win32acm/wine/winestring.h</path>
<path>win32acm/wine/winnt.h</path>
<path>win32acm/wine/winreg.h</path>
<path>win32acm/wine/winuser.h</path>
<path>win32acm/wineacm.h</path>
<path>win32acm/wrapper.h</path>
<path>builddate.h</path>
</blacklist>
<build>
<buildtool>make</buildtool>
<builddir/>
</build>
<other>
<prio>0</prio>
<otherbin/>
<defaulttarget/>
<otheroptions/>
<selectedenvironment>default</selectedenvironment>
<environments>
<default/>
</environments>
</other>
<make>
<abortonerror>true</abortonerror>
<numberofjobs>0</numberofjobs>
<prio>0</prio>
<dontact>false</dontact>
<makebin/>
<defaulttarget/>
<makeoptions/>
<selectedenvironment>default</selectedenvironment>
<environments>
<default/>
</environments>
</make>
</kdevcustomproject>
<kdevdebugger>
<general>
<dbgshell/>
<gdbpath/>
<configGdbScript/>
<runShellScript/>
<runGdbScript/>
<breakonloadinglibs>true</breakonloadinglibs>
<separatetty>false</separatetty>
<floatingtoolbar>false</floatingtoolbar>
<raiseGDBOnStart>false</raiseGDBOnStart>
</general>
<display>
<staticmembers>false</staticmembers>
<demanglenames>true</demanglenames>
<outputradix>10</outputradix>
</display>
</kdevdebugger>
<kdevdoctreeview>
<ignoretocs>
<toc>ada</toc>
<toc>ada_bugs_gcc</toc>
<toc>bash</toc>
<toc>bash_bugs</toc>
<toc>clanlib</toc>
<toc>fortran_bugs_gcc</toc>
<toc>gnome1</toc>
<toc>gnustep</toc>
<toc>gtk</toc>
<toc>gtk_bugs</toc>
<toc>haskell</toc>
<toc>haskell_bugs_ghc</toc>
<toc>java_bugs_gcc</toc>
<toc>java_bugs_sun</toc>
<toc>kde2book</toc>
<toc>libstdc++</toc>
<toc>opengl</toc>
<toc>pascal_bugs_fp</toc>
<toc>php</toc>
<toc>php_bugs</toc>
<toc>perl</toc>
<toc>perl_bugs</toc>
<toc>python</toc>
<toc>python_bugs</toc>
<toc>qt-kdev3</toc>
<toc>ruby</toc>
<toc>ruby_bugs</toc>
<toc>sdl</toc>
<toc>stl</toc>
<toc>sw</toc>
<toc>w3c-dom-level2-html</toc>
<toc>w3c-svg</toc>
<toc>w3c-uaag10</toc>
<toc>wxwidgets_bugs</toc>
</ignoretocs>
<ignoreqt_xml>
<toc>Guide to the Qt Translation Tools</toc>
<toc>Qt Assistant Manual</toc>
<toc>Qt Designer Manual</toc>
<toc>Qt Reference Documentation</toc>
<toc>qmake User Guide</toc>
</ignoreqt_xml>
<ignoredoxygen>
<toc>KDE Libraries (Doxygen)</toc>
</ignoredoxygen>
</kdevdoctreeview>
<kdevfilecreate>
<filetypes/>
<useglobaltypes>
<type ext="c" />
<type ext="h" />
</useglobaltypes>
</kdevfilecreate>
<kdevcppsupport>
<qt>
<used>false</used>
<version>3</version>
<includestyle>3</includestyle>
<root></root>
<designerintegration>EmbeddedKDevDesigner</designerintegration>
<qmake></qmake>
<designer></designer>
<designerpluginpaths/>
</qt>
<references/>
<codecompletion>
<automaticCodeCompletion>false</automaticCodeCompletion>
<automaticArgumentsHint>true</automaticArgumentsHint>
<automaticHeaderCompletion>true</automaticHeaderCompletion>
<codeCompletionDelay>250</codeCompletionDelay>
<argumentsHintDelay>400</argumentsHintDelay>
<headerCompletionDelay>250</headerCompletionDelay>
<showOnlyAccessibleItems>false</showOnlyAccessibleItems>
<completionBoxItemOrder>0</completionBoxItemOrder>
<howEvaluationContextMenu>true</howEvaluationContextMenu>
<showCommentWithArgumentHint>true</showCommentWithArgumentHint>
<statusBarTypeEvaluation>false</statusBarTypeEvaluation>
<namespaceAliases>std=_GLIBCXX_STD;__gnu_cxx=std</namespaceAliases>
<processPrimaryTypes>true</processPrimaryTypes>
<processFunctionArguments>false</processFunctionArguments>
<preProcessAllHeaders>false</preProcessAllHeaders>
<parseMissingHeadersExperimental>false</parseMissingHeadersExperimental>
<resolveIncludePathsUsingMakeExperimental>false</resolveIncludePathsUsingMakeExperimental>
<alwaysParseInBackground>true</alwaysParseInBackground>
<usePermanentCaching>true</usePermanentCaching>
<alwaysIncludeNamespaces>false</alwaysIncludeNamespaces>
<includePaths>.;</includePaths>
</codecompletion>
<creategettersetter>
<prefixGet/>
<prefixSet>set</prefixSet>
<prefixVariable>m_,_</prefixVariable>
<parameterName>theValue</parameterName>
<inlineGet>true</inlineGet>
<inlineSet>true</inlineSet>
</creategettersetter>
<splitheadersource>
<enabled>false</enabled>
<synchronize>true</synchronize>
<orientation>Vertical</orientation>
</splitheadersource>
</kdevcppsupport>
<kdevfileview>
<groups>
<hidenonprojectfiles>false</hidenonprojectfiles>
<hidenonlocation>false</hidenonlocation>
</groups>
<tree>
<hidepatterns>*.o,*.lo,CVS</hidepatterns>
<hidenonprojectfiles>false</hidenonprojectfiles>
</tree>
</kdevfileview>
<cppsupportpart>
<filetemplates>
<interfacesuffix>.h</interfacesuffix>
<implementationsuffix>.cpp</implementationsuffix>
</filetemplates>
</cppsupportpart>
</kdevelop>

View file

@ -20,6 +20,19 @@ EXOSIP_LIBS="$OSIP_LIBS -leXosip2 "
CPPFLAGS_save=$CPPFLAGS
CPPFLAGS="$OSIP_CFLAGS $CPPFLAGS"
AC_CHECK_HEADER([eXosip2/eXosip.h], ,AC_MSG_ERROR([Could not find eXosip2 headers !]))
dnl check exosip support of DSCP in exosip
AC_MSG_CHECKING([for DSCP support in exosip])
AC_TRY_COMPILE([#include <eXosip2/eXosip.h>],
[int dscp=0;eXosip_set_option(EXOSIP_OPT_SET_DSCP,&dscp);],
has_exosip_dscp=yes,
has_exosip_dscp=no
)
AC_MSG_RESULT($has_exosip_dscp)
if test "$has_exosip_dscp" = "yes" ; then
AC_DEFINE( HAVE_EXOSIP_DSCP, 1, [Define if exosip dscp available] )
fi
CPPFLAGS=$CPPFLAGS_save

@ -1 +1 @@
Subproject commit d5811e376759433da3c19585b2d8d0329e1c06b2
Subproject commit 4ccd8ca511eb46375699f5efaf8f41b655e0dbb8

2
oRTP

@ -1 +1 @@
Subproject commit 20abeb39e1edae0f72080f7998410e9b16b9da05
Subproject commit 020d921f876ed04d434425fb2176642bbe9b3004

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