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

This commit is contained in:
Jehan Monnier 2011-02-15 15:08:23 +01:00
commit aadd9b0b02
81 changed files with 10544 additions and 11861 deletions

60
AUTHORS
View file

@ -1,57 +1,13 @@
Simon MORLAT (simon dot morlat at linphone dot org) wrotes:
- main graphical program (gnome)
- RTP library (oRTP)
- SIP user-agent library (osipua)
- audio library (mediastreamer), for codec and i/o handling.
- sipomatic, the automatic sip replier, which is often used for testing.
Main authors:
Florian Wintertein < f-win at gmx dot net > wrotes the console version of linphone (linphonec)
Belledonne Communications SARL team:
Simon Morlat, Jehan Monnier, Guillaume Beraudo
Contributors:
Florian Wintertein < f-win at gmx dot net > originaly wrotes the console version of linphone (linphonec)
in console/ directory.
Aymeric Moizard (jack at atosc dot org) wrotes:
- the oSIP SIP transactionnal stack (not part of linphone)
- some piece of code of the osip distribution have been reused in osipua
- presence information support in osipua
- and contributes to some parts of osipua (digest authentification)
For more information about oSIP, see http://osip.atosc.org
Sharath Udupa is developing the media_api, a usefull library to manage audio and video streams
for basic calls as well as conference.
Sandro Santilli < strk at keybit dot net > wrote enhancements in the
console interface (readline, new commands) and some bug fixes for
the core api.
console interface (readline, new commands).
Bryan Ogawa ( bko at cisco dot com ) sent a patch that made the linphone-0.7.1 release.
This patch fixed several issues in the SIP part while working with proxies.
Koichi KUNITAKE < kunitake at linux-ipv6 dot org > has contributed a patch bringing
full IPv6 support.
The Speex codec is a project from Jean Marc Valin. See http://speex.sourceforge.net for more
information.
The GSM library was written by :
Jutta Degener and Carsten Bormann,Technische Universitaet Berlin.
The LPC10-1.5 library was written by:
Andy Fingerhut
Applied Research Laboratory <-- this line is optional if
Washington University, Campus Box 1045/Bryan 509 you have limited space
One Brookings Drive
Saint Louis, MO 63130-4899
jaf@arl.wustl.edu
http://www.arl.wustl.edu/~jaf/
See text files in gsmlib and lpc10-1.5 directories for further information.
G711 library has some code from the alsa-lib on http://www.alsa-project.org
Icons by Pablo Marcelo Moia.
Translations:
fr: Simon Morlat
en: Simon Morlat and Delphine Perreau
it: Alberto Zanoni <alberto.zanoni@-NO-SPAM-PLEASE!-tiscalinet.it>
de: Jean-Jacques Sarton <jj.sarton@-NO-SPAM-PLEASE-t-online.de>
es: Jesús Benítez <gnelson at inMail dot sk>

View file

@ -48,16 +48,16 @@ SDK_EXCLUDED= \
$(OPTIONAL_SOUNDS)
GTK_PREFIX=/usr
GTK_PREFIX=/
GTK_THEME=Outcrop
GTK_FILELIST=gtk+-2.18.5.filelist
GTK_FILELIST=gtk+-2.22.1.filelist
GTK_FILELIST_PATH=$(shell cd $(top_srcdir) && pwd)/$(GTK_FILELIST)
LINPHONEDEPS_FILELIST=linphone-deps.filelist
WINBINDIST_FILES=$(shell cat $(top_srcdir)/$(LINPHONEDEPS_FILELIST))
ISS_SCRIPT=linphone.iss
ISS_SCRIPT_PATH=$(shell cd $(top_srcdir) && pwd)/$(ISS_SCRIPT)
#path to Inno Setup 5 compiler
ISCC=/c/Program\ Files/Inno\ Setup\ 5/ISCC.exe
ISCC=ISCC.exe
PACKAGE_WIN32_FILELIST=$(PACKAGE)-win32.filelist
EXTRA_DIST = config.rpath BUGS linphone.kdevelop \
@ -109,7 +109,11 @@ other-cherrypick:
cp $$file $(INSTALLDIR_WITH_PREFIX)/$$file ;\
fi \
done
cp /mingw/bin/libgcc_s*.dll $(INSTALLDIR_WITH_PREFIX)/bin/.
cp /mingw/bin/libgcc_s*.dll \
/mingw/bin/libstdc++-6.dll \
/mingw/bin/libintl-8.dll \
/mingw/bin/libiconv-2.dll \
$(INSTALLDIR_WITH_PREFIX)/bin/.
gtk-cherrypick:

19
NEWS
View file

@ -1,3 +1,22 @@
linphone-3.4.0 -- February 7th, 2011
* implement multiple calls feature:
- call hold (with possibility to play a music file)
- call resume
- acceptance of 2nd call while putting the others on hold
- creation of another outgoing call while already in call
- blind call transfer
- attended call transfer
**CAUTION**: LinphoneCoreVTable has changed: pay attention to this when upgrading an old application to a newer liblinphone.
* improve bandwidth management (one b=AS line is used for audio+video)
* improvements in the echo limiter performance
* implement a echo calibration feature (see linphone_core_start_echo_calibration()).
* stun support bugfixes
* possibility to use two video windows, one for local preview, one for remote video (linphonec only)
* optimize by not re-creating streams when SDP is unchanged during a reinvite
* support for sending early media
* doxygen doc and javadoc improvements
* based on mediastreamer-2.7.0, please refer to mediastreamer NEWS for changes.
linphone-3.3.2 -- July 1st, 2010
* fix crash when setting firewall address in gtk interface
* fix crash while closing video window on windows

10
README
View file

@ -5,16 +5,16 @@ This is Linphone, a free (GPL) video softphone based on the SIP protocol.
- you need at least:
- libosip2>=3.0.3
- libeXosip2>=3.0.3
- speex>=1.1.6
- libreadline
- 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
- libglade>=2.2
+ if you want video support:
- SDL>=1.2.10
- libavcodec (ffmpeg) from a year 2007 or later cvs/svn
- libavcodec (ffmpeg)
- libswscale (part of ffmpeg too) for better scaling performance
- theora (optional)
with their corresponding -dev or -devel package if you don't use source packages.
@ -38,7 +38,7 @@ Here is a short description of the content of the source tree.
- coreapi/ is the central point of linphone, which handles relationship between sip signalisation and media
streaming. It contains an easy to use api to create a sip phone.
- gtk-glade/ is the directory that contains the gui frontend of linphone. It uses all libraries descibed above.
- gtk/ is the directory that contains the gui frontend of linphone. It uses all libraries descibed above.
- console/
* linphonec.c is the main file for the console version of linphone.

View file

@ -1,61 +1,57 @@
Software to install
*******************
* mingw32, using Automated windows installer (when launched, choose candidate to have lastest binaries)
* msys, using windows installer too.
Download lastest mingw-get-inst.exe from http://www.mingw.org
Run mingw-get-inst.exe. Choose "download lastest catalogues".
In the feature list, select:
* C compiler
* C++ compiler
* Mingw developer toolkit
Let the installer fetch and install everything.
run msys as Administrator (right click on the icon, and click 'run as administrator')
In mingw shell, run
Download zip and unzip (download setup.exe and run) from http://gnuwin32.sourceforge.net
- add them to your path in msys terminal:
export PATH=$PATH:/c/Program\ Files/GnuWin32/bin
mingw-get install msys-zip
mingw-get install msys-unzip
mingw-get install msys-wget
Download from mingw download page (http://www.mingw.org, click download):
- MSYS automake-1.11
- MSYS autoconf-2.63
- MSYS libtool>=2.2.7
- MSYS libcrypt*-bin
- MSYS perl
- MSYS gettext-*bin* and gettext-*dev*
===> Uncompress all these packages in /
- from gcc-4.4 directory
Download:
- gcc-core*-bin
- gcc-core-*-dll
- gcc-c++*-bin
- gcc-c++*-dll
- gmp*-dll
- mpfr*-dll
- w32api*-dev
- mingwrt-dev and mingwrt-dll (mingw run time)
- gnu binutils 2.19
===> Uncompress all these packages in /mingw
mkdir -p /opt/perl/bin
cp /bin/perl /opt/perl/bin/.
note: lzma files can be uncompressed using tar --lzma -xvf <file>
cd ~
#Download intltool
wget http://ftp.acc.umu.se/pub/GNOME/binaries/win32/intltool/0.40/intltool_0.40.4-1_win32.zip
* Download intltool (quicklink:
http://ftp.acc.umu.se/pub/GNOME/binaries/win32/intltool/0.40/intltool_0.40.4-1_win32.zip
note: -dev package is not needed.)
uncompress in / with 'unzip' command.
Download lastest linphone-deps-win32 zip from
http://download.savannah.gnu.org/releases-noredirect/linphone/misc
using your browser.
* Download lastest gtk+bundle from http://www.gtk.org , uncompress in /
* Download libglade and libglade-dev >=2.6.3 from gnome ftp:
http://ftp.gnome.org/pub/GNOME/binaries/win32/libglade/2.6/libglade-dev_2.6.4-1_win32.zip
http://ftp.gnome.org/pub/GNOME/binaries/win32/libglade/2.6/libglade_2.6.4-1_win32.zip
uncompress in /
* Download ActiveState perl and run the installer with default options (http://www.activestate.com , developer tools)
Yes it is required despite MSYS perl is already installed.
Download lastest gtk+ win32 bundle from http://www.gtk.org
* Download lastest linphone-deps from linphone downloads, misc directory:
http://download.savannah.gnu.org/releases-noredirect/linphone/misc/)
uncompress in /
* Download and install Inno Setup Compiler in its default path (required only if you run 'make setup.exe').
Install all these three package in /:
* HACKS:
Move out /lib/libintl.la : it confuses libtool
mv /lib/libintl.la /lib/libintl.la.bak
Move out libstdc++.la in order to workaround a gcc-4.4.0 bug (or packaging bug):
mv /mingw/lib/gcc/mingw32/4.4.0/libstdc++.la /mingw/lib/gcc/mingw32/4.4.0/libstdc++.la.bak
cd /
unzip ~/intltool_0.40.4-1_win32.zip
unzip <path to gtk bundle zip>
unzip <path to linphone-deps>
#Install GTK+ Outcrop theme, the one used by linphone for distribution.
cd /share/themes
wget http://art.gnome.org/download/themes/gtk2/1122/GTK2-Outcrop.tar.gz
tar -xvzf GTK2-Outcrop.tar.gz
#Remove the special stdint.h and inttypes.h included in linphone-deps: it is for MSVC only.
#Mingw will use the one in /mingw/include
rm /include/stdint.h /include/inttypes.h
#Remove libgcc specific libraries, only needed for MSVC:
rm /lib/libgcc.a /lib/libmingw32.a /lib/libmingwex.a
#Remove libintl from gtk, we don't need it and it conflicts with the one supplied by mingw.
rm /lib/libintl.dll.a
rm /include/intl.h
* Download and install Inno Setup Compiler (required only if you run 'make setup.exe'). Add it to your windows Path environment variable.
Get Linphone source code
************************
@ -66,7 +62,7 @@ It is recommended that you create a directory somewhere with a path without any
c:\sources\
Within msys-git bash, do
cd /c/sources
git clone git://git.savannah.nongnu.org/linphone.git
git clone git://git.savannah.nongnu.org/linphone.git --recursive
Building
@ -76,17 +72,6 @@ WARNING: During the build, windows might slow down suddenly. Using ctl+alt+del t
you might see a process 'LVpSRV.exe' or something like this that eats 90% of cpu.
Kill it. Don't know what it is, but once killed, windows runs normally.
The following variables must be exported:
#use ActiveState perl instead of mingw perl
export PERL="/c/Perl/bin/perl"
export INTLTOOL_PERL="/c/Perl/bin/perl"
#add gnuwin32 tools to your path:
export PATH=$PATH:/c/Program\ Files/Gnuwin32/bin
for convenience the 'mingw-envsetup.sh' script in linphone sources does this, so you can just source it:
. ./mingw-envsetup.sh
#run autogen.sh after a git checkout or update
./autogen.sh
./configure --prefix=/opt/linphone --enable-shared --disable-static
@ -97,6 +82,7 @@ make install
make zip
#additionally you can make binary installer if you have Inno Setup 5 installed in its default path
make setup.exe
#now you're done, you have a fresh linphone windows installer in the current directory.
#build plugins
cd mediastreamer2/plugins/msx264

View file

@ -20,6 +20,10 @@ if test -d /opt/local/share/aclocal ; then
ACLOCAL_ARGS="-I /opt/local/share/aclocal"
fi
if test -d /share/aclocal ; then
ACLOCAL_ARGS="$ACLOCAL_ARGS -I /share/aclocal"
fi
if test -f /opt/local/bin/intltoolize ; then
#darwin
INTLTOOLIZE=/opt/local/bin/intltoolize

View file

@ -46,13 +46,14 @@ LOCAL_SRC_FILES = \
sal_eXosip2_sdp.c \
offeranswer.c \
callbacks.c \
linphonecall.c
linphonecall.c \
ec-calibrator.c
LOCAL_CFLAGS += \
-D_BYTE_ORDER=_LITTLE_ENDIAN \
-DORTP_INET6 \
-DENABLE_TRACE \
-DLINPHONE_VERSION=\"Linphone-3.3.x\" \
-DLINPHONE_VERSION=\"3.4.0\" \
-DLINPHONE_PLUGINS_DIR=\"\\tmp\" \
-DLOG_DOMAIN=\"Linphone\"
@ -72,10 +73,11 @@ LOCAL_C_INCLUDES += \
LOCAL_LDLIBS += -llog -ldl
LOCAL_STATIC_LIBRARIES := \
libmediastreamer2 \
libortp \
libspeex \
libeXosip2 \
libosip2 \
libgsm
@ -85,9 +87,14 @@ LOCAL_STATIC_LIBRARIES += \
libavcodec \
libswscale \
libavcore \
libavutil
libavutil \
libmsx264 \
libx264
endif
LOCAL_STATIC_LIBRARIES += libspeex
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
LOCAL_CFLAGS += -DHAVE_ILBC=1
LOCAL_STATIC_LIBRARIES += libmsilbc

View file

@ -1,6 +1,6 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT([linphone],[3.3.99.10],[linphone-developers@nongnu.org])
AC_INIT([linphone],[3.4.1],[linphone-developers@nongnu.org])
AC_CANONICAL_SYSTEM
AC_CONFIG_SRCDIR([coreapi/linphonecore.c])
@ -95,25 +95,19 @@ AC_SUBST(ALL_LINGUAS)
AC_DEFINE_UNQUOTED(LINPHONE_ALL_LANGS, "$ALL_LINGUAS", [All supported languages])
if test "$mingw_found" != "yes" ; then
dnl gettext macro does not work properly under mingw.
dnl gettext macro does not work properly under mingw. And we want to use the one provided by GTK.
AM_GNU_GETTEXT([external])
LIBS="$LIBS $LIBINTL"
else
if test "$mingwce_found" != "yes" ; then
AC_DEFINE(ENABLE_NLS,1,[Tells whether localisation is possible])
AC_DEFINE(HAVE_GETTEXT,1,[Tells wheter localisation is possible])
LIBS="$LIBS -L/usr/lib -lintl"
else
dnl gettext macro does not work properly under mingw.
AM_GNU_GETTEXT([external])
LIBS="$LIBS $LIBINTL"
fi
AC_DEFINE(ENABLE_NLS,1,[Tells whether localisation is possible])
AC_DEFINE(HAVE_GETTEXT,1,[Tells wheter localisation is possible])
LIBS="$LIBS -lintl"
fi
GETTEXT_PACKAGE=linphone
AC_SUBST(GETTEXT_PACKAGE)
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE",[The name of the gettext package name])
AC_CHECK_LIB(intl,libintl_gettext)
dnl AC_CHECK_LIB(intl,libintl_gettext)
AC_CHECK_FUNCS([get_current_dir_name strndup stpcpy] )
@ -304,7 +298,9 @@ AC_ARG_ENABLE(x11,
if test "$video" = "true"; then
if test "$enable_x11" = "true"; then
AC_CHECK_HEADERS(X11/Xlib.h)
AC_CHECK_HEADERS(X11/Xlib.h)
AC_CHECK_LIB(X11,XUnmapWindow, X11_LIBS="-lX11")
AC_SUBST(X11_LIBS)
fi
AC_DEFINE(VIDEO_ENABLED,1,[defined if video support is available])
fi

View file

@ -23,7 +23,8 @@ linphonec_LDADD = $(top_builddir)/coreapi/liblinphone.la $(READLINE_LIBS) \
$(MEDIASTREAMER_LIBS) \
$(ORTP_LIBS) \
$(SPEEX_LIBS) \
$(OSIP_LIBS)
$(OSIP_LIBS) \
$(X11_LIBS)
if BUILD_WIN32
#special build of linphonec to detach from the windows console
@ -33,17 +34,6 @@ linphoned_LDADD=$(linphonec_LDADD)
endif
sipomatic_SOURCES=\
sipomatic.c sipomatic.h
sipomatic_CFLAGS= $(COMMON_CFLAGS) $(CONSOLE_FLAGS)
sipomatic_LDADD= $(INTLLIBS) \
$(top_builddir)/coreapi/liblinphone.la \
$(MEDIASTREAMER_LIBS) \
$(ORTP_LIBS) \
$(SPEEX_LIBS) \
$(OSIP_LIBS)
linphonecsh_SOURCES = shell.c
linphonecsh_CFLAGS = $(CONSOLE_FLAGS)
linphonecsh_LDADD = $(ORTP_LIBS)

View file

@ -83,6 +83,7 @@ static int lpc_cmd_acodec(LinphoneCore *lc, char *args);
static int lpc_cmd_vcodec(LinphoneCore *lc, char *args);
static int lpc_cmd_codec(int type, LinphoneCore *lc, char *args);
static int lpc_cmd_echocancellation(LinphoneCore *lc, char *args);
static int lpc_cmd_echolimiter(LinphoneCore *lc, char *args);
static int lpc_cmd_pause(LinphoneCore *lc, char *args);
static int lpc_cmd_resume(LinphoneCore *lc, char *args);
static int lpc_cmd_mute_mic(LinphoneCore *lc, char *args);
@ -93,6 +94,7 @@ static int lpc_cmd_camera(LinphoneCore *lc, char *args);
static int lpc_cmd_video_window(LinphoneCore *lc, char *args);
static int lpc_cmd_preview_window(LinphoneCore *lc, char *args);
static int lpc_cmd_snapshot(LinphoneCore *lc, char *args);
static int lpc_cmd_vfureq(LinphoneCore *lc, char *arg);
#endif
static int lpc_cmd_states(LinphoneCore *lc, char *args);
static int lpc_cmd_identify(LinphoneCore *lc, char *args);
@ -269,6 +271,10 @@ static LPC_COMMAND advanced_commands[] = {
"'ec on [<delay>] [<tail>] [<framesize>]' : turn EC on with given delay, tail length and framesize\n"
"'ec off' : turn echo cancellation (EC) off\n"
"'ec show' : show EC status" },
{ "el", lpc_cmd_echolimiter, "Echo limiter",
"'el on turns on echo limiter (automatic half duplex, for cases where echo canceller cannot work)\n"
"'el off' : turn echo limiter off\n"
"'el show' : show echo limiter status" },
{ "nortp-on-audio-mute", lpc_cmd_rtp_no_xmit_on_audio_mute,
"Set the rtp_no_xmit_on_audio_mute configuration parameter",
" If set to 1 then rtp transmission will be muted when\n"
@ -293,6 +299,7 @@ static LPC_COMMAND advanced_commands[] = {
{ "snapshot", lpc_cmd_snapshot, "Take a snapshot of currently received video stream",
"'snapshot <file path>': take a snapshot and records it in jpeg format into the supplied path\n"
},
{ "vfureq", lpc_cmd_vfureq, "Request the other side to send VFU for the current call"},
#endif
{ "states", lpc_cmd_states, "Show internal states of liblinphone, registrations and calls, according to linphonecore.h definitions",
"'states global': shows global state of liblinphone \n"
@ -1948,10 +1955,18 @@ static int lpc_cmd_status(LinphoneCore *lc, char *args)
LinphoneCallState call_state=LinphoneCallIdle;
if (call) call_state=linphone_call_get_state(call);
switch(call_state){
switch(call_state){
case LinphoneCallOutgoingInit:
linphonec_out("hook=outgoing_init sip:%s\n",linphonec_get_callee());
break;
case LinphoneCallOutgoingProgress:
linphonec_out("hook=dialing\n");
linphonec_out("hook=dialing sip:%s\n",linphonec_get_callee());
break;
case LinphoneCallOutgoingRinging:
linphonec_out("hook=ringing sip:%s\n",linphonec_get_callee());
break;
case LinphoneCallPaused:
linphonec_out("hook=paused sip:%s\n",linphonec_get_callee());
break;
case LinphoneCallIdle:
linphonec_out("hook=offhook\n");
@ -1964,8 +1979,8 @@ static int lpc_cmd_status(LinphoneCore *lc, char *args)
linphone_core_is_mic_muted (lc) ? "yes" : "no",
linphone_core_is_rtp_muted(lc) ? "yes" : "no");
}else{
linphonec_out("hook=answered duration=%i\n" ,
linphone_core_get_current_call_duration(lc));
linphonec_out("hook=answered duration=%i %s\n" ,
linphone_core_get_current_call_duration(lc), linphonec_get_caller());
}
break;
case LinphoneCallIncomingReceived:
@ -2202,6 +2217,18 @@ static int lpc_cmd_echocancellation(LinphoneCore *lc, char *args){
return 1;
}
static int lpc_cmd_echolimiter(LinphoneCore *lc, char *args){
if (args){
if (strcmp(args,"on")==0){
linphone_core_enable_echo_limiter (lc,TRUE);
}else if (strcmp(args,"off")==0){
linphone_core_enable_echo_limiter (lc,FALSE);
}
}
linphonec_out("Echo limiter is now %s.\n",linphone_core_echo_limiter_enabled (lc) ? "on":"off");
return 1;
}
static int lpc_cmd_mute_mic(LinphoneCore *lc, char *args)
{
linphone_core_mute_mic(lc, 1);
@ -2408,12 +2435,21 @@ static int lpc_cmd_snapshot(LinphoneCore *lc, char *args){
if (!args) return 0;
call=linphone_core_get_current_call(lc);
if (call!=NULL){
linphone_call_take_video_snapshot (call,args);
linphonec_out("Taking video snaphot in file %s\n", args);
linphone_call_take_video_snapshot(call,args);
linphonec_out("Taking video snapshot in file %s\n", args);
}else linphonec_out("There is no active call.\n");
return 1;
}
static int lpc_cmd_vfureq(LinphoneCore *lc, char *arg){
LinphoneCall *call;
call=linphone_core_get_current_call(lc);
if (call!=NULL){
linphone_call_send_vfu_request(call);
linphonec_out("VFU request sent\n");
}else linphonec_out("There is no active call.\n");
return 1;
}
#endif
static int lpc_cmd_identify(LinphoneCore *lc, char *args){

View file

@ -34,6 +34,7 @@
#endif /*_WIN32_WCE*/
#include <limits.h>
#include <ctype.h>
#include <stdlib.h>
#include <linphonecore.h>
@ -79,7 +80,6 @@
#ifdef HAVE_X11_XLIB_H
#include <X11/Xlib.h>
#include <SDL/SDL_syswm.h>
#endif
/***************************************************************************
@ -162,6 +162,7 @@ static char *logfile_name = NULL;
static char configfile_name[PATH_MAX];
static const char *factory_configfile_name=NULL;
static char *sipAddr = NULL; /* for autocall */
static int window_id = 0; /* 0=standalone window, or window id for embedding video */
#if !defined(_WIN32_WCE)
static ortp_pipe_t client_sock=ORTP_PIPE_INVALID;
#endif /*_WIN32_WCE*/
@ -391,7 +392,7 @@ static void
linphonec_text_received(LinphoneCore *lc, LinphoneChatRoom *cr,
const LinphoneAddress *from, const char *msg)
{
printf("%s: %s\n", linphone_address_as_string(from), msg);
linphonec_out("Message received from %s: %s\n", linphone_address_as_string(from), msg);
// TODO: provide mechanism for answering.. ('say' command?)
}
@ -716,6 +717,12 @@ linphonec_init(int argc, char **argv)
*/
linphonec=linphone_core_new (&linphonec_vtable, configfile_name, factory_configfile_name, NULL);
linphone_core_enable_video(linphonec,vcap_enabled,display_enabled);
if (display_enabled && window_id != 0)
{
printf ("Setting window_id: 0x%x\n", window_id);
linphone_core_set_native_video_window_id(linphonec,window_id);
}
linphone_core_enable_video_preview(linphonec,preview_enabled);
if (!(vcap_enabled || display_enabled)) printf("Warning: video is disabled in linphonec, use -V or -C or -D to enable.\n");
#ifdef HAVE_READLINE
@ -878,6 +885,7 @@ usage: linphonec [-c file] [-s sipaddr] [-a] [-V] [-d level ] [-l logfile]\n\
-C enable video capture only (disabled by default)\n\
-D enable video display only (disabled by default)\n\
-S show general state messages (disabled by default)\n\
--wid windowid force embedding of video window into provided windowid (disabled by default)\n\
-v or --version display version and exits.\n");
exit(exit_status);
@ -1226,6 +1234,14 @@ linphonec_parse_cmdline(int argc, char **argv)
{
unix_socket=1;
}
else if (strncmp ("--wid", argv[arg_num], 5) == 0)
{
arg_num++;
if (arg_num < argc) {
char *tmp;
window_id = strtol( argv[arg_num], &tmp, 0 );
}
}
else if (old_arg_num == arg_num)
{
fprintf (stderr, "ERROR: bad arguments\n");

View file

@ -66,7 +66,7 @@ void sipomatic_process_event(Sipomatic *obj,eXosip_event_t *ev)
}
void endoffile_cb(void *ud, unsigned int ev,void * arg){
void endoffile_cb(void *ud, MSFilter *f, unsigned int ev,void * arg){
Call*call=(Call*)ud;
call->eof=1;
}

View file

@ -35,7 +35,8 @@ liblinphone_la_SOURCES=\
linphonecall.c \
sipsetup.c sipsetup.h \
siplogin.c \
lsd.c linphonecore_utils.h
lsd.c linphonecore_utils.h \
ec-calibrator.c
liblinphone_la_LDFLAGS= -version-info $(LIBLINPHONE_SO_VERSION) -no-undefined
@ -49,7 +50,7 @@ if BUILD_WIN32
liblinphone_la_LIBADD+=$(top_builddir)/oRTP/src/libortp.la
endif
noinst_PROGRAMS=test_lsd
noinst_PROGRAMS=test_lsd test_ecc
test_lsd_SOURCES=test_lsd.c
@ -57,6 +58,14 @@ test_lsd_LDADD=liblinphone.la \
$(MEDIASTREAMER_LIBS) \
$(ORTP_LIBS)
test_ecc_SOURCES=test_ecc.c
test_ecc_LDADD=liblinphone.la \
$(MEDIASTREAMER_LIBS) \
$(ORTP_LIBS)
AM_CFLAGS=$(STRICT_OPTIONS) -DIN_LINPHONE \
$(ORTP_CFLAGS) \
$(OSIP_CFLAGS) \

View file

@ -193,21 +193,26 @@ static void call_received(SalOp *h){
}else{
/*TODO : play a tone within the context of the current call */
}
linphone_call_ref(call); /*prevent the call from being destroyed while we are notifying, if the user declines within the state callback */
linphone_call_set_state(call,LinphoneCallIncomingReceived,"Incoming call");
sal_call_notify_ringing(h,propose_early_media || ringback_tone!=NULL);
if (call->state==LinphoneCallIncomingReceived){
sal_call_notify_ringing(h,propose_early_media || ringback_tone!=NULL);
if (propose_early_media || ringback_tone!=NULL){
linphone_call_set_state(call,LinphoneCallIncomingEarlyMedia,"Incoming call early media");
linphone_core_update_streams(lc,call,md);
if (propose_early_media || ringback_tone!=NULL){
linphone_call_set_state(call,LinphoneCallIncomingEarlyMedia,"Incoming call early media");
linphone_core_update_streams(lc,call,md);
}
if (sal_call_get_replaces(call->op)!=NULL && lp_config_get_int(lc->config,"sip","auto_answer_replacing_calls",1)){
linphone_core_accept_call(lc,call);
}
}
linphone_call_unref(call);
ms_free(barmesg);
ms_free(tmp);
if (sal_call_get_replaces(call->op)!=NULL && lp_config_get_int(lc->config,"sip","auto_answer_replacing_calls",1)){
linphone_core_accept_call(lc,call);
}
}
static void call_ringing(SalOp *h){
@ -286,6 +291,7 @@ static void call_accepted(SalOp *op){
ms_free(tmp);
ms_free(msg);
}
linphone_core_update_streams (lc,call,md);
linphone_call_set_state(call,LinphoneCallPaused,"Call paused");
}else if (sal_media_description_has_dir(md,SalStreamRecvOnly)){
/*we are put on hold when the call is initially accepted */
@ -296,19 +302,32 @@ static void call_accepted(SalOp *op){
ms_free(tmp);
ms_free(msg);
}
linphone_call_set_state(call,LinphoneCallPaused,"Call paused");
linphone_core_update_streams (lc,call,md);
linphone_call_set_state(call,LinphoneCallPausedByRemote,"Call paused by remote");
}else{
if (lc->vtable.display_status){
lc->vtable.display_status(lc,_("Call answered - connected."));
}
if (call->state==LinphoneCallStreamsRunning){
/*media was running before, the remote as acceted a call modification (that is
a reinvite made by us. We must notify the application this reinvite was accepted*/
linphone_call_set_state(call, LinphoneCallUpdated, "Call updated");
}else{
if (call->state==LinphoneCallResuming){
if (lc->vtable.display_status){
lc->vtable.display_status(lc,_("Call resumed."));
}
}else{
if (lc->vtable.display_status){
char *tmp=linphone_call_get_remote_address_as_string (call);
char *msg=ms_strdup_printf(_("Call answered by %s."),tmp);
lc->vtable.display_status(lc,msg);
ms_free(tmp);
ms_free(msg);
}
}
}
linphone_call_set_state(call,LinphoneCallStreamsRunning,"Connected (streams running)");
linphone_core_update_streams (lc,call,md);
linphone_call_set_state(call, LinphoneCallStreamsRunning, "Streams running");
lc->current_call=call;
}
linphone_core_update_streams (lc,call,md);
}else{
/*send a bye*/
ms_error("Incompatible SDP offer received in 200Ok, need to abort the call");
@ -342,6 +361,7 @@ static void call_ack(SalOp *op){
}
}
/* this callback is called when an incoming re-INVITE modifies the session*/
static void call_updating(SalOp *op){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op));
@ -353,32 +373,22 @@ static void call_updating(SalOp *op){
if (md && !sal_media_description_empty(md))
{
if ((call->state==LinphoneCallPausedByRemote || call->state==LinphoneCallPaused) &&
sal_media_description_has_dir(md,SalStreamSendRecv) && strcmp(md->addr,"0.0.0.0")!=0){
/*make sure we can be resumed */
if (lc->current_call!=NULL && lc->current_call!=call){
ms_warning("Attempt to be resumed but already in call with somebody else!");
/*we are actively running another call, reject with a busy*/
sal_call_decline (op,SalReasonBusy,NULL);
return;
if (sal_media_description_has_dir(call->localdesc,SalStreamSendRecv)){
ms_message("Our local status is SalStreamSendRecv");
if (sal_media_description_has_dir (md,SalStreamRecvOnly) || sal_media_description_has_dir(md,SalStreamInactive)){
/* we are being paused */
if(lc->vtable.display_status)
lc->vtable.display_status(lc,_("We are being paused..."));
linphone_call_set_state (call,LinphoneCallPausedByRemote,"Call paused by remote");
}else if (!sal_media_description_has_dir(call->resultdesc,SalStreamSendRecv) && sal_media_description_has_dir(md,SalStreamSendRecv)){
if(lc->vtable.display_status)
lc->vtable.display_status(lc,_("We have been resumed..."));
linphone_call_set_state (call,LinphoneCallStreamsRunning,"Connected (streams running)");
lc->current_call=call;
}else{
prevstate=call->state;
linphone_call_set_state(call, LinphoneCallUpdatedByRemote,"Call updated by remote");
}
if(lc->vtable.display_status)
lc->vtable.display_status(lc,_("We have been resumed..."));
linphone_call_set_state (call,LinphoneCallStreamsRunning,"Connected (streams running)");
}
else if(call->state==LinphoneCallStreamsRunning &&
( sal_media_description_has_dir(md,SalStreamRecvOnly)
|| sal_media_description_has_dir(md,SalStreamInactive)
|| strcmp(md->addr,"0.0.0.0")==0)){
if(lc->vtable.display_status)
lc->vtable.display_status(lc,_("We are being paused..."));
linphone_call_set_state (call,LinphoneCallPausedByRemote,"Call paused by remote");
if (lc->current_call!=call){
ms_error("Inconsitency detected: current call is %p but call %p is being paused !",lc->current_call,call);
}
}else{
prevstate=call->state;
linphone_call_set_state(call, LinphoneCallUpdatedByRemote,"Call updated by remote");
}
/*accept the modification (sends a 200Ok)*/
sal_call_accept(op);
@ -494,6 +504,13 @@ static void call_failure(SalOp *op, SalError error, SalReason sr, const char *de
}
}
static void call_released(SalOp *op){
LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op);
if (call!=NULL){
linphone_call_set_state(call,LinphoneCallReleased,"Call released");
}else ms_error("call_released() for already destroyed call ?");
}
static void auth_requested(SalOp *h, const char *realm, const char *username){
LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h));
LinphoneAuthInfo *ai=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,realm,username);
@ -509,7 +526,7 @@ static void auth_requested(SalOp *h, const char *realm, const char *username){
ai->usecount++;
}else{
if (ai && ai->works==FALSE) {
register_failure(h, SalErrorFailure, SalReasonForbidden, _("Authentication failure"));
sal_op_cancel_authentication(h);
}
if (lc->vtable.auth_info_requested)
lc->vtable.auth_info_requested(lc,realm,username);
@ -669,6 +686,7 @@ SalCallbacks linphone_sal_callbacks={
call_updating,
call_terminated,
call_failure,
call_released,
auth_requested,
auth_success,
register_success,

179
coreapi/ec-calibrator.c Normal file
View file

@ -0,0 +1,179 @@
/*
linphone
Copyright (C) 2011 Belledonne Communications SARL
Author: Simon MORLAT (simon.morlat@linphone.org)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "private.h"
#include "mediastreamer2/mstonedetector.h"
#include "mediastreamer2/dtmfgen.h"
static void ecc_init_filters(EcCalibrator *ecc){
ecc->ticker=ms_ticker_new();
ecc->sndread=ms_snd_card_create_reader(ecc->play_card);
ecc->det=ms_filter_new(MS_TONE_DETECTOR_ID);
ecc->rec=ms_filter_new(MS_FILE_REC_ID);
ms_filter_link(ecc->sndread,0,ecc->det,0);
ms_filter_link(ecc->det,0,ecc->rec,0);
ecc->play=ms_filter_new(MS_FILE_PLAYER_ID);
ecc->gen=ms_filter_new(MS_DTMF_GEN_ID);
ecc->resampler=ms_filter_new(MS_RESAMPLE_ID);
ecc->sndwrite=ms_snd_card_create_writer(ecc->capt_card);
ms_filter_link(ecc->play,0,ecc->gen,0);
ms_filter_link(ecc->gen,0,ecc->resampler,0);
ms_filter_link(ecc->resampler,0,ecc->sndwrite,0);
unsigned int rate;
ms_filter_call_method(ecc->sndwrite,MS_FILTER_GET_SAMPLE_RATE,&rate);
ms_filter_call_method(ecc->resampler,MS_FILTER_SET_OUTPUT_SAMPLE_RATE,&rate);
ms_ticker_attach(ecc->ticker,ecc->play);
ms_ticker_attach(ecc->ticker,ecc->sndread);
}
static void ecc_deinit_filters(EcCalibrator *ecc){
ms_ticker_detach(ecc->ticker,ecc->play);
ms_ticker_detach(ecc->ticker,ecc->sndread);
ms_filter_unlink(ecc->play,0,ecc->gen,0);
ms_filter_unlink(ecc->gen,0,ecc->resampler,0);
ms_filter_unlink(ecc->resampler,0,ecc->sndwrite,0);
ms_filter_unlink(ecc->sndread,0,ecc->det,0);
ms_filter_unlink(ecc->det,0,ecc->rec,0);
ms_filter_destroy(ecc->sndread);
ms_filter_destroy(ecc->det);
ms_filter_destroy(ecc->rec);
ms_filter_destroy(ecc->play);
ms_filter_destroy(ecc->gen);
ms_filter_destroy(ecc->resampler);
ms_filter_destroy(ecc->sndwrite);
ms_ticker_destroy(ecc->ticker);
}
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 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);
}
static void ecc_play_tones(EcCalibrator *ecc){
MSDtmfGenCustomTone tone;
MSToneDetectorDef expected_tone;
ms_filter_set_notify_callback(ecc->det,on_tone_received,ecc);
expected_tone.frequency=2000;
expected_tone.min_duration=40;
expected_tone.min_amplitude=0.02;
ms_filter_call_method (ecc->det,MS_TONE_DETECTOR_ADD_SCAN,&expected_tone);
tone.frequency=1000;
tone.duration=1000;
tone.amplitude=1.0;
/*play an initial tone to startup the audio playback/capture*/
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;
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 && 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{
ms_error("Echo calibration failed, tones received = %i",ecc->recv_count);
ecc->status=LinphoneEcCalibratorFailed;
}
}
static void * ecc_thread(void *p){
EcCalibrator *ecc=(EcCalibrator*)p;
ecc_init_filters(ecc);
ecc_play_tones(ecc);
ecc_deinit_filters(ecc);
ms_thread_exit(NULL);
return NULL;
}
EcCalibrator * ec_calibrator_new(MSSndCard *play_card, MSSndCard *capt_card, LinphoneEcCalibrationCallback cb, void *cb_data ){
EcCalibrator *ecc=ms_new0(EcCalibrator,1);
ecc->cb=cb;
ecc->cb_data=cb_data;
ecc->capt_card=capt_card;
ecc->play_card=play_card;
ms_thread_create(&ecc->thread,NULL,ecc_thread,ecc);
return ecc;
}
LinphoneEcCalibratorStatus ec_calibrator_get_status(EcCalibrator *ecc){
return ecc->status;
}
void ec_calibrator_destroy(EcCalibrator *ecc){
ms_thread_join(ecc->thread,NULL);
ms_free(ecc);
}
int linphone_core_start_echo_calibration(LinphoneCore *lc, LinphoneEcCalibrationCallback cb, void *cb_data){
if (lc->ecc!=NULL){
ms_error("Echo calibration is still on going !");
return -1;
}
lc->ecc=ec_calibrator_new(lc->sound_conf.play_sndcard,lc->sound_conf.capt_sndcard,cb,cb_data);
return 0;
}

View file

@ -277,7 +277,9 @@ SalPresenceStatus linphone_online_status_to_sal(LinphoneOnlineStatus os){
}
void linphone_friend_notify(LinphoneFriend *lf, LinphoneOnlineStatus os){
//printf("Wish to notify %p, lf->nid=%i\n",lf,lf->nid);
char *addr=linphone_address_as_string(linphone_friend_get_address(lf));
ms_message("Want to notify %s, insub=%p",addr,lf->insub);
ms_free(addr);
if (lf->insub!=NULL){
sal_notify_presence(lf->insub,linphone_online_status_to_sal(os),NULL);
}
@ -286,8 +288,6 @@ void linphone_friend_notify(LinphoneFriend *lf, LinphoneOnlineStatus os){
static void linphone_friend_unsubscribe(LinphoneFriend *lf){
if (lf->outsub!=NULL) {
sal_unsubscribe(lf->outsub);
sal_op_release(lf->outsub);
lf->outsub=NULL;
lf->subscribe_active=FALSE;
}
}
@ -296,13 +296,19 @@ void linphone_friend_close_subscriptions(LinphoneFriend *lf){
linphone_friend_unsubscribe(lf);
if (lf->insub){
sal_notify_close(lf->insub);
sal_op_release(lf->insub);
lf->insub=NULL;
}
}
void linphone_friend_destroy(LinphoneFriend *lf){
if (lf->insub) {
sal_op_release(lf->insub);
lf->insub=NULL;
}
if (lf->outsub){
sal_op_release(lf->outsub);
lf->outsub=NULL;
}
if (lf->uri!=NULL) linphone_address_destroy(lf->uri);
if (lf->info!=NULL) buddy_info_free(lf->info);
ms_free(lf);

View file

@ -80,7 +80,7 @@ WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = . ../
INPUT = @top_srcdir@/coreapi @top_srcdir@/coreapi/help
FILE_PATTERNS = *.h \
*.c \
@ -89,7 +89,7 @@ RECURSIVE = NO
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS =
EXAMPLE_PATH = ../../ .
EXAMPLE_PATH = @top_srcdir@ @top_srcdir@/coreapi/help
EXAMPLE_PATTERNS =
EXAMPLE_RECURSIVE = NO
IMAGE_PATH =

View file

@ -32,23 +32,29 @@ endif
clean-local:
rm -rf doc
#tutorials
noinst_PROGRAMS=helloworld registration buddy_status chatroom
helloworld_SOURCES=helloworld.c
LINPHONE_TUTOS=$(helloworld_SOURCES)
helloworld_LDADD=$(top_builddir)/coreapi/liblinphone.la \
$(MEDIASTREAMER_LIBS) \
$(ORTP_LIBS)
registration_SOURCES=registration.c
LINPHONE_TUTOS+=$(registration_SOURCES)
registration_LDADD=$(helloworld_LDADD)
buddy_status_SOURCES=buddy_status.c
LINPHONE_TUTOS+=$(buddy_status_SOURCES)
buddy_status_LDADD=$(helloworld_LDADD)
chatroom_SOURCES=chatroom.c
LINPHONE_TUTOS+=$(chatroom_SOURCES)
chatroom_LDADD=$(helloworld_LDADD)
@ -68,3 +74,7 @@ AM_CFLAGS=$(STRICT_OPTIONS) -DIN_LINPHONE \
-DORTP_INET6 \
$(VIDEO_CFLAGS)
tutodir=$(datadir)/tutorials/linphone
tuto_DATA=$(LINPHONE_TUTOS)

View file

@ -66,19 +66,36 @@ static void new_subscription_request (LinphoneCore *lc, LinphoneFriend *friend,
linphone_core_add_friend(lc,friend); /* add this new friend to the buddy list*/
}
/**
* Registration state notification callback
*/
static void registration_state_changed(struct _LinphoneCore *lc, LinphoneProxyConfig *cfg, LinphoneRegistrationState cstate, const char *message){
printf("New registration state %s for user id [%s] at proxy [%s]\n"
,linphone_registration_state_to_string(cstate)
,linphone_proxy_config_get_identity(cfg)
,linphone_proxy_config_get_addr(cfg));
}
LinphoneCore *lc;
int main(int argc, char *argv[]){
LinphoneCoreVTable vtable={0};
char* dest_friend=NULL;
char* identity=NULL;
char* password=NULL;
/* takes sip uri identity from the command line arguments */
if (argc>1){
dest_friend=argv[1];
}
/* takes sip uri identity from the command line arguments */
if (argc>2){
identity=argv[2];
}
/* takes password from the command line arguments */
if (argc>3){
password=argv[3];
}
signal(SIGINT,stop);
//#define DEBUG
#ifdef DEBUG
@ -91,11 +108,47 @@ int main(int argc, char *argv[]){
*/
vtable.notify_presence_recv=notify_presence_recv_updated;
vtable.new_subscription_request=new_subscription_request;
vtable.registration_state_changed=registration_state_changed; /*just in case sip proxy is used*/
/*
Instantiate a LinphoneCore object given the LinphoneCoreVTable
*/
lc=linphone_core_new(&vtable,NULL,NULL,NULL);
/*sip proxy might be requested*/
if (identity != NULL) {
/*create proxy config*/
LinphoneProxyConfig* proxy_cfg = linphone_proxy_config_new();
/*parse identity*/
LinphoneAddress *from = linphone_address_new(identity);
if (from==NULL){
printf("%s not a valid sip uri, must be like sip:toto@sip.linphone.org \n",identity);
goto end;
}
LinphoneAuthInfo *info;
if (password!=NULL){
info=linphone_auth_info_new(linphone_address_get_username(from),NULL,password,NULL,NULL); /*create authentication structure from identity*/
linphone_core_add_auth_info(lc,info); /*add authentication info to LinphoneCore*/
}
// configure proxy entries
linphone_proxy_config_set_identity(proxy_cfg,identity); /*set identity with user name and domain*/
linphone_proxy_config_set_server_addr(proxy_cfg,linphone_address_get_domain(from)); /* we assume domain = proxy server address*/
linphone_proxy_config_enable_register(proxy_cfg,TRUE); /*activate registration for this proxy config*/
linphone_proxy_config_enable_publish(proxy_cfg,TRUE); /* enable presence satus publication for this proxy*/
linphone_address_destroy(from); /*release resource*/
linphone_core_add_proxy_config(lc,proxy_cfg); /*add proxy config to linphone core*/
linphone_core_set_default_proxy(lc,proxy_cfg); /*set to default proxy*/
/* Loop until registration status is available */
do {
linphone_core_iterate(lc); /* first iterate initiates registration */
ms_usleep(100000);
}
while( running && linphone_proxy_config_get_state(proxy_cfg) == LinphoneRegistrationProgress);
}
LinphoneFriend* my_friend=NULL;
if (dest_friend) {

View file

@ -34,6 +34,13 @@
/**
* @defgroup call_control Placing and receiving calls
*
* The #LinphoneCall object represents an incoming or outgoing call managed by the #LinphoneCore.
* Outgoing calls can be created using linphone_core_invite() or linphone_core_invite_address(), while incoming calls are notified to the application
* through the LinphoneCoreVTable::call_state_changed callback.
*
* See the basic call \ref basic_call_tutorials "tutorial".
*
**/
/**

View file

@ -22,6 +22,7 @@ import org.linphone.core.LinphoneAddress;
import org.linphone.core.LinphoneCall;
import org.linphone.core.LinphoneChatRoom;
import org.linphone.core.LinphoneCore;
import org.linphone.core.LinphoneCore.EcCalibratorStatus;
import org.linphone.core.LinphoneCoreException;
import org.linphone.core.LinphoneCoreFactory;
import org.linphone.core.LinphoneCoreListener;
@ -40,7 +41,9 @@ import org.linphone.core.LinphoneFriend.SubscribePolicy;
* from a sip uri identity passed from the command line.
* <br>Argument must be like sip:jehan@sip.linphone.org .
* ex budy_list sip:jehan@sip.linphone.org
* <br>Subscription is cleared on SIGINT
* <br>
* Optionnally argument 2 can be registration sip identy.Argument 3 can be passord.
* ex: budy_list sip:jehan@sip.linphone.org sip:myidentity@sip.linphone.org mypassword
*
* Ported from buddy_status.c
*
@ -81,7 +84,9 @@ public class TutorialBuddyStatus implements LinphoneCoreListener {
}
public void registrationState(LinphoneCore lc, LinphoneProxyConfig cfg,RegistrationState cstate, String smessage) {}
public void registrationState(LinphoneCore lc, LinphoneProxyConfig cfg,RegistrationState cstate, String smessage) {
write(cfg.getIdentity() + " : "+smessage+"\n");
}
public void show(LinphoneCore lc) {}
public void byeReceived(LinphoneCore lc, String from) {}
public void authInfoRequested(LinphoneCore lc, String realm, String username) {}
@ -91,14 +96,14 @@ public class TutorialBuddyStatus implements LinphoneCoreListener {
public void globalState(LinphoneCore lc, GlobalState state, String message) {}
public void textReceived(LinphoneCore lc, LinphoneChatRoom cr,LinphoneAddress from, String message) {}
public void callState(LinphoneCore lc, LinphoneCall call, State cstate, String msg) {}
public void ecCalibrationStatus(LinphoneCore lc, EcCalibratorStatus status,int delay_ms, Object data) {}
public static void main(String[] args) {
// Check tutorial was called with the right number of arguments
if (args.length != 1) {
throw new IllegalArgumentException("Bad number of arguments");
if (args.length < 1 || args.length > 3 ) {
throw new IllegalArgumentException("Bad number of arguments ["+args.length+"] should be 1, 2 or 3");
}
// Create tutorial object
@ -106,7 +111,13 @@ public class TutorialBuddyStatus implements LinphoneCoreListener {
try {
// takes sip uri identity from the command line arguments
String userSipAddress = args[1];
tutorial.launchTutorial(userSipAddress);
// takes sip uri identity from the command line arguments
String mySipAddress = args.length>1?args[1]:null;
// takes password from the command line arguments
String mySipPassword =args.length>2?args[2]:null;
tutorial.launchTutorial(userSipAddress,mySipAddress,mySipPassword);
} catch (Exception e) {
e.printStackTrace();
}
@ -114,7 +125,7 @@ public class TutorialBuddyStatus implements LinphoneCoreListener {
public void launchTutorial(String sipAddress) throws LinphoneCoreException {
public void launchTutorial(String sipAddress,String mySipAddress, String mySipPassword) throws LinphoneCoreException {
final LinphoneCoreFactory lcFactory = LinphoneCoreFactory.instance();
// First instantiate the core Linphone object given only a listener.
@ -131,6 +142,34 @@ public class TutorialBuddyStatus implements LinphoneCoreListener {
return;
}
if (mySipAddress != null) {
// Parse identity
LinphoneAddress address = lcFactory.createLinphoneAddress(mySipAddress);
String username = address.getUserName();
String domain = address.getDomain();
if (mySipPassword != null) {
// create authentication structure from identity and add to linphone
lc.addAuthInfo(lcFactory.createAuthInfo(username, mySipPassword, null));
}
// create proxy config
LinphoneProxyConfig proxyCfg = lcFactory.createProxyConfig(mySipAddress, domain, null, true);
proxyCfg.enablePublish(true);
lc.addProxyConfig(proxyCfg); // add it to linphone
lc.setDefaultProxyConfig(proxyCfg);
while (!proxyCfg.isRegistered()) {
lc.iterate(); //iterate until registration
try{
Thread.sleep(1000);
} catch(InterruptedException ie) {
write("Interrupted!\nAborting");
return;
}
}
}
// configure this friend to emit SUBSCRIBE message after being added to LinphoneCore
lf.enableSubscribes(true);
@ -191,4 +230,6 @@ public class TutorialBuddyStatus implements LinphoneCoreListener {
TutorialNotifier.notify(s);
}
}

View file

@ -22,6 +22,7 @@ import org.linphone.core.LinphoneAddress;
import org.linphone.core.LinphoneCall;
import org.linphone.core.LinphoneChatRoom;
import org.linphone.core.LinphoneCore;
import org.linphone.core.LinphoneCore.EcCalibratorStatus;
import org.linphone.core.LinphoneCoreException;
import org.linphone.core.LinphoneCoreFactory;
import org.linphone.core.LinphoneCoreListener;
@ -73,7 +74,7 @@ public class TutorialChatRoom implements LinphoneCoreListener {
public void newSubscriptionRequest(LinphoneCore lc, LinphoneFriend lf,String url) {}
public void notifyPresenceReceived(LinphoneCore lc, LinphoneFriend lf) {}
public void callState(LinphoneCore lc, LinphoneCall call, State cstate, String msg){}
public void ecCalibrationStatus(LinphoneCore lc, EcCalibratorStatus status,int delay_ms, Object data) {}
public void textReceived(LinphoneCore lc, LinphoneChatRoom cr,LinphoneAddress from, String message) {
@ -144,4 +145,5 @@ public class TutorialChatRoom implements LinphoneCoreListener {
TutorialNotifier.notify(s);
}
}

View file

@ -22,6 +22,7 @@ import org.linphone.core.LinphoneAddress;
import org.linphone.core.LinphoneCall;
import org.linphone.core.LinphoneChatRoom;
import org.linphone.core.LinphoneCore;
import org.linphone.core.LinphoneCore.EcCalibratorStatus;
import org.linphone.core.LinphoneCoreException;
import org.linphone.core.LinphoneCoreFactory;
import org.linphone.core.LinphoneCoreListener;
@ -67,7 +68,7 @@ public class TutorialHelloWorld implements LinphoneCoreListener {
public void newSubscriptionRequest(LinphoneCore lc, LinphoneFriend lf,String url) {}
public void notifyPresenceReceived(LinphoneCore lc, LinphoneFriend lf) {}
public void textReceived(LinphoneCore lc, LinphoneChatRoom cr,LinphoneAddress from, String message) {}
public void ecCalibrationStatus(LinphoneCore lc, EcCalibratorStatus status,int delay_ms, Object data) {}
/*
* Call state notification listener
*/
@ -153,4 +154,5 @@ public class TutorialHelloWorld implements LinphoneCoreListener {
TutorialNotifier.notify(s);
}
}

View file

@ -22,6 +22,7 @@ import org.linphone.core.LinphoneAddress;
import org.linphone.core.LinphoneCall;
import org.linphone.core.LinphoneChatRoom;
import org.linphone.core.LinphoneCore;
import org.linphone.core.LinphoneCore.EcCalibratorStatus;
import org.linphone.core.LinphoneCoreException;
import org.linphone.core.LinphoneCoreFactory;
import org.linphone.core.LinphoneCoreListener;
@ -64,10 +65,7 @@ public class TutorialRegistration implements LinphoneCoreListener {
* Registration state notification listener
*/
public void registrationState(LinphoneCore lc, LinphoneProxyConfig cfg,RegistrationState cstate, String smessage) {
write(cfg.getIdentity() + " : "+smessage+"\n");
if (RegistrationState.RegistrationOk.equals(cstate))
running = false;
write(cfg.getIdentity() + " : "+smessage);
}
public void show(LinphoneCore lc) {}
@ -81,7 +79,7 @@ public class TutorialRegistration implements LinphoneCoreListener {
public void notifyPresenceReceived(LinphoneCore lc, LinphoneFriend lf) {}
public void textReceived(LinphoneCore lc, LinphoneChatRoom cr,LinphoneAddress from, String message) {}
public void callState(LinphoneCore lc, LinphoneCall call, State cstate, String msg) {}
public void ecCalibrationStatus(LinphoneCore lc, EcCalibratorStatus status,int delay_ms, Object data) {}
public static void main(String[] args) {
// Check tutorial was called with the right number of arguments
@ -127,36 +125,56 @@ public class TutorialRegistration implements LinphoneCoreListener {
// create proxy config
LinphoneProxyConfig proxyCfg = lcFactory.createProxyConfig(sipAddress, domain, null, true);
proxyCfg.setExpires(2000);
lc.addProxyConfig(proxyCfg); // add it to linphone
lc.setDefaultProxyConfig(proxyCfg);
// main loop for receiving notifications and doing background linphonecore work
running = true;
while (running) {
lc.iterate(); // first iterate initiates registration
try{
Thread.sleep(50);
} catch(InterruptedException ie) {
write("Interrupted!\nAborting");
return;
}
sleep(50);
}
// Unregister
lc.getDefaultProxyConfig().edit();
lc.getDefaultProxyConfig().enableRegister(false);
lc.getDefaultProxyConfig().done();
while(lc.getDefaultProxyConfig().getState() != RegistrationState.RegistrationCleared) {
lc.iterate();
sleep(50);
}
// Then register again
lc.getDefaultProxyConfig().edit();
lc.getDefaultProxyConfig().enableRegister(true);
lc.getDefaultProxyConfig().done();
while(lc.getDefaultProxyConfig().getState() != RegistrationState.RegistrationOk
&& lc.getDefaultProxyConfig().getState() != RegistrationState.RegistrationFailed) {
lc.iterate();
sleep(50);
}
// Automatic unregistration on exit
} finally {
write("Shutting down...");
write("Shutting down linphone...");
// You need to destroy the LinphoneCore object when no longer used
lc.destroy();
write("Exited");
}
}
private void sleep(int ms) {
try {
Thread.sleep(ms);
} catch(InterruptedException ie) {
write("Interrupted!\nAborting");
return;
}
}
public void stopMainLoop() {
running=false;
@ -167,4 +185,6 @@ public class TutorialRegistration implements LinphoneCoreListener {
TutorialNotifier.notify(s);
}
}

View file

@ -32,6 +32,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "mediastreamer2/msequalizer.h"
#include "mediastreamer2/msfileplayer.h"
#include "mediastreamer2/msjpegwriter.h"
#include "mediastreamer2/mseventqueue.h"
#ifdef VIDEO_ENABLED
static MSWebCam *get_nowebcam_device(){
@ -58,18 +59,21 @@ static MSList *make_codec_list(LinphoneCore *lc, const MSList *codecs, int bandw
return l;
}
SalMediaDescription *create_local_media_description(LinphoneCore *lc, LinphoneCall *call){
static SalMediaDescription *_create_local_media_description(LinphoneCore *lc, LinphoneCall *call, unsigned int session_id, unsigned int session_ver){
MSList *l;
PayloadType *pt;
const char *me=linphone_core_get_identity(lc);
LinphoneAddress *addr=linphone_address_new(me);
const char *username=linphone_address_get_username (addr);
SalMediaDescription *md=sal_media_description_new();
md->session_id=session_id;
md->session_ver=session_ver;
md->nstreams=1;
strncpy(md->addr,call->localip,sizeof(md->addr));
strncpy(md->username,username,sizeof(md->username));
md->bandwidth=linphone_core_get_download_bandwidth(lc);
/*set audio capabilities */
strncpy(md->streams[0].addr,call->localip,sizeof(md->streams[0].addr));
md->streams[0].port=call->audio_port;
@ -81,8 +85,6 @@ SalMediaDescription *create_local_media_description(LinphoneCore *lc, LinphoneCa
l=ms_list_append(l,pt);
md->streams[0].payloads=l;
if (lc->dw_audio_bw>0)
md->streams[0].bandwidth=lc->dw_audio_bw;
if (call->params.has_video){
md->nstreams++;
@ -91,13 +93,27 @@ SalMediaDescription *create_local_media_description(LinphoneCore *lc, LinphoneCa
md->streams[1].type=SalVideo;
l=make_codec_list(lc,lc->codecs_conf.video_codecs,0);
md->streams[1].payloads=l;
if (lc->dw_video_bw)
md->streams[1].bandwidth=lc->dw_video_bw;
}
linphone_address_destroy(addr);
return md;
}
void update_local_media_description(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription **md){
if (*md == NULL) {
*md = _create_local_media_description(lc,call,0,0);
} else {
unsigned int id = (*md)->session_id;
unsigned int ver = (*md)->session_ver+1;
sal_media_description_unref(*md);
*md = _create_local_media_description(lc,call,id,ver);
}
}
SalMediaDescription *create_local_media_description(LinphoneCore *lc, LinphoneCall *call){
unsigned int id=rand();
return _create_local_media_description(lc,call,id,id);
}
static int find_port_offset(LinphoneCore *lc){
int offset;
MSList *elem;
@ -129,6 +145,7 @@ static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from,
call->start_time=time(NULL);
call->media_start_time=0;
call->log=linphone_call_log_new(call, from, to);
call->owns_call_log=TRUE;
linphone_core_notify_all_friends(call->core,LinphoneStatusOnThePhone);
port_offset=find_port_offset (call->core);
if (port_offset==-1) return;
@ -225,8 +242,10 @@ static void linphone_call_set_terminated(LinphoneCall *call){
else status=LinphoneCallSuccess;
}
call->owns_call_log=FALSE;
linphone_call_log_completed(call->log,call, status);
if (call == lc->current_call){
ms_message("Resetting the current call");
lc->current_call=NULL;
@ -239,13 +258,6 @@ static void linphone_call_set_terminated(LinphoneCall *call){
if (ms_list_size(lc->calls)==0)
linphone_core_notify_all_friends(lc,lc->presence_mode);
if (call->op!=NULL) {
/* so that we cannot have anymore upcalls for SAL
concerning this call*/
sal_op_release(call->op);
call->op=NULL;
}
linphone_call_unref(call);
}
const char *linphone_call_state_to_string(LinphoneCallState cs){
@ -286,14 +298,23 @@ const char *linphone_call_state_to_string(LinphoneCallState cs){
return "LinphoneCallIncomingEarlyMedia";
case LinphoneCallUpdated:
return "LinphoneCallUpdated";
case LinphoneCallReleased:
return "LinphoneCallReleased";
}
return "undefined state";
}
void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const char *message){
LinphoneCore *lc=call->core;
bool_t finalize_call=FALSE;
if (call->state!=cstate){
if (call->state==LinphoneCallEnd || call->state==LinphoneCallError){
if (cstate!=LinphoneCallReleased){
ms_warning("Spurious call state change from %s to %s, ignored.",linphone_call_state_to_string(call->state),
linphone_call_state_to_string(cstate));
return;
}
}
ms_message("Call %p: moving from state %s to %s",call,linphone_call_state_to_string(call->state),
linphone_call_state_to_string(cstate));
if (cstate!=LinphoneCallRefered){
@ -302,14 +323,20 @@ void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const
call->state=cstate;
}
if (cstate==LinphoneCallEnd || cstate==LinphoneCallError){
finalize_call=TRUE;
linphone_call_ref(call);
linphone_call_set_terminated (call);
}
if (lc->vtable.call_state_changed)
lc->vtable.call_state_changed(lc,call,cstate,message);
if (finalize_call)
if (cstate==LinphoneCallReleased){
if (call->op!=NULL) {
/* so that we cannot have anymore upcalls for SAL
concerning this call*/
sal_op_release(call->op);
call->op=NULL;
}
linphone_call_unref(call);
}
}
}
@ -333,6 +360,8 @@ static void linphone_call_destroy(LinphoneCall *obj)
if (obj->refer_to){
ms_free(obj->refer_to);
}
if (obj->owns_call_log)
linphone_call_log_destroy(obj->log);
ms_free(obj);
}
@ -367,7 +396,7 @@ void linphone_call_unref(LinphoneCall *obj){
* Returns current parameters associated to the call.
**/
const LinphoneCallParams * linphone_call_get_current_params(const LinphoneCall *call){
return &call->params;
return &call->current_params;
}
/**
@ -476,6 +505,20 @@ int linphone_call_get_duration(const LinphoneCall *call){
return time(NULL)-call->media_start_time;
}
/**
* Returns the call object this call is replacing, if any.
* Call replacement can occur during call transfers.
* By default, the core automatically terminates the replaced call and accept the new one.
* This function allows the application to know whether a new incoming call is a one that replaces another one.
**/
LinphoneCall *linphone_call_get_replaced_call(LinphoneCall *call){
SalOp *op=sal_call_get_replaces(call->op);
if (op){
return (LinphoneCall*)sal_op_get_user_pointer(op);
}
return NULL;
}
/**
* Indicate whether camera input should be sent to remote end.
**/
@ -508,21 +551,21 @@ int linphone_call_take_video_snapshot(LinphoneCall *call, const char *file){
}
/**
*
* Returns TRUE if camera pictures are sent to the remote party.
**/
bool_t linphone_call_camera_enabled (const LinphoneCall *call){
return call->camera_active;
}
/**
*
* Enable video stream.
**/
void linphone_call_params_enable_video(LinphoneCallParams *cp, bool_t enabled){
cp->has_video=enabled;
}
/**
*
* Returns whether video is enabled.
**/
bool_t linphone_call_params_video_enabled(const LinphoneCallParams *cp){
return cp->has_video;
@ -575,6 +618,21 @@ static void rendercb(void *data, const MSPicture *local, const MSPicture *remote
}
#endif
#ifdef VIDEO_ENABLED
static void video_stream_event_cb(void *user_pointer, const MSFilter *f, const unsigned int event_id, const void *args){
ms_warning("In linphonecall.c: video_stream_event_cb");
switch (event_id) {
case MS_VIDEO_DECODER_DECODING_ERRORS:
ms_warning("CAse is MS_VIDEO_DECODER_DECODING_ERRORS");
linphone_call_send_vfu_request((LinphoneCall*) user_pointer);
break;
default:
ms_warning("Unhandled event %i", event_id);
break;
}
}
#endif
void linphone_call_init_media_streams(LinphoneCall *call){
LinphoneCore *lc=call->core;
SalMediaDescription *md=call->localdesc;
@ -609,6 +667,7 @@ void linphone_call_init_media_streams(LinphoneCall *call){
call->videostream=video_stream_new(md->streams[1].port,linphone_core_ipv6_enabled(lc));
if( lc->video_conf.displaytype != NULL)
video_stream_set_display_filter_name(call->videostream,lc->video_conf.displaytype);
video_stream_set_event_callback(call->videostream,video_stream_event_cb, call);
#ifdef TEST_EXT_RENDERER
video_stream_set_render_callback(call->videostream,rendercb,NULL);
#endif
@ -675,27 +734,24 @@ static void post_configure_audio_streams(LinphoneCall*call){
}
if (st->volsend){
ms_filter_call_method(st->volsend,MS_VOLUME_REMOVE_DC,&dc_removal);
}
if (linphone_core_echo_limiter_enabled(lc)){
float speed=lp_config_get_float(lc->config,"sound","el_speed",-1);
thres=lp_config_get_float(lc->config,"sound","el_thres",-1);
float force=lp_config_get_float(lc->config,"sound","el_force",-1);
int sustain=lp_config_get_int(lc->config,"sound","el_sustain",-1);
float transmit_thres=lp_config_get_float(lc->config,"sound","el_transmit_thres",-1);
MSFilter *f=NULL;
if (st->el_type!=ELInactive){
f=st->volsend;
if (speed==-1) speed=0.03;
if (force==-1) force=25;
ms_filter_call_method(f,MS_VOLUME_SET_EA_SPEED,&speed);
ms_filter_call_method(f,MS_VOLUME_SET_EA_FORCE,&force);
if (thres!=-1)
ms_filter_call_method(f,MS_VOLUME_SET_EA_THRESHOLD,&thres);
if (sustain!=-1)
ms_filter_call_method(f,MS_VOLUME_SET_EA_SUSTAIN,&sustain);
}
}
if (st->volsend){
f=st->volsend;
if (speed==-1) speed=0.03;
if (force==-1) force=25;
ms_filter_call_method(f,MS_VOLUME_SET_EA_SPEED,&speed);
ms_filter_call_method(f,MS_VOLUME_SET_EA_FORCE,&force);
if (thres!=-1)
ms_filter_call_method(f,MS_VOLUME_SET_EA_THRESHOLD,&thres);
if (sustain!=-1)
ms_filter_call_method(f,MS_VOLUME_SET_EA_SUSTAIN,&sustain);
if (transmit_thres!=-1)
ms_filter_call_method(f,MS_VOLUME_SET_EA_TRANSMIT_THRESHOLD,&transmit_thres);
ms_filter_call_method(st->volsend,MS_VOLUME_SET_NOISE_GATE_THRESHOLD,&ng_thres);
ms_filter_call_method(st->volsend,MS_VOLUME_SET_NOISE_GATE_FLOORGAIN,&ng_floorgain);
}
@ -716,12 +772,13 @@ static void post_configure_audio_streams(LinphoneCall*call){
static RtpProfile *make_profile(LinphoneCore *lc, const SalMediaDescription *md, const SalStreamDescription *desc, int *used_pt){
static RtpProfile *make_profile(LinphoneCall *call, const SalMediaDescription *md, const SalStreamDescription *desc, int *used_pt){
int bw;
const MSList *elem;
RtpProfile *prof=rtp_profile_new("Call profile");
bool_t first=TRUE;
int remote_bw=0;
LinphoneCore *lc=call->core;
*used_pt=-1;
for(elem=desc->payloads;elem!=NULL;elem=elem->next){
@ -730,7 +787,7 @@ static RtpProfile *make_profile(LinphoneCore *lc, const SalMediaDescription *md,
if (first) {
if (desc->type==SalAudio){
linphone_core_update_allocated_audio_bandwidth_in_call(lc,pt);
linphone_core_update_allocated_audio_bandwidth_in_call(call,pt);
}
*used_pt=payload_type_get_number(pt);
first=FALSE;
@ -740,13 +797,13 @@ static RtpProfile *make_profile(LinphoneCore *lc, const SalMediaDescription *md,
/*case where b=AS is given globally, not per stream*/
remote_bw=md->bandwidth;
if (desc->type==SalVideo){
remote_bw-=lc->audio_bw;
remote_bw=get_video_bandwidth(remote_bw,call->audio_bw);
}
}
if (desc->type==SalAudio){
bw=get_min_bandwidth(lc->up_audio_bw,remote_bw);
}else bw=get_min_bandwidth(lc->up_video_bw,remote_bw);
bw=get_min_bandwidth(call->audio_bw,remote_bw);
}else bw=get_min_bandwidth(get_video_bandwidth(linphone_core_get_upload_bandwidth (lc),call->audio_bw),remote_bw);
if (bw>0) pt->normal_bitrate=bw*1000;
else if (desc->type==SalAudio){
pt->normal_bitrate=-1;
@ -779,12 +836,17 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut
const char *tool="linphone-" LINPHONE_VERSION;
char *cname;
int used_pt=-1;
#ifdef VIDEO_ENABLED
const SalStreamDescription *vstream=sal_media_description_find_stream(call->resultdesc,
SalProtoRtpAvp,SalVideo);
#endif
if(call->audiostream == NULL)
{
ms_fatal("start_media_stream() called without prior init !");
return;
}
call->current_params = call->params;
/* adjust rtp jitter compensation. It must be at least the latency of the sound card */
int jitt_comp=MAX(lc->sound_conf.latency,lc->rtp_conf.audio_jitt_comp);
@ -800,7 +862,9 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut
MSSndCard *captcard=lc->sound_conf.capt_sndcard;
const char *playfile=lc->play_file;
const char *recfile=lc->rec_file;
call->audio_profile=make_profile(lc,call->resultdesc,stream,&used_pt);
call->audio_profile=make_profile(call,call->resultdesc,stream,&used_pt);
bool_t use_ec;
if (used_pt!=-1){
if (playcard==NULL) {
ms_warning("No card defined for playback !");
@ -817,7 +881,8 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut
playcard=NULL;
captcard=NULL;
recfile=NULL;
playfile=NULL;
/*And we will eventually play "playfile" if set by the user*/
/*playfile=NULL;*/
}
if (send_ringbacktone){
captcard=NULL;
@ -828,6 +893,12 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut
captcard=NULL;
playcard=NULL;
}
use_ec=captcard==NULL ? FALSE : linphone_core_echo_cancellation_enabled(lc);
#if defined(VIDEO_ENABLED) && defined(ANDROID)
/*On android we have to disable the echo canceller to preserve CPU for video codecs */
if (vstream && vstream->dir!=SalStreamInactive && vstream->payloads!=NULL)
use_ec=FALSE;
#endif
audio_stream_start_full(
call->audiostream,
call->audio_profile,
@ -840,11 +911,16 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut
recfile,
playcard,
captcard,
captcard==NULL ? FALSE : linphone_core_echo_cancellation_enabled(lc));
use_ec
);
post_configure_audio_streams(call);
if (all_inputs_muted && !send_ringbacktone){
audio_stream_set_mic_gain(call->audiostream,0);
}
if (stream->dir==SalStreamSendOnly && playfile!=NULL){
int pause_time=500;
ms_filter_call_method(call->audiostream->soundread,MS_FILE_PLAYER_LOOP,&pause_time);
}
if (send_ringbacktone){
setup_ring_player(lc,call);
}
@ -854,23 +930,23 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut
}
#ifdef VIDEO_ENABLED
{
const SalStreamDescription *stream=sal_media_description_find_stream(call->resultdesc,
SalProtoRtpAvp,SalVideo);
used_pt=-1;
/* shutdown preview */
if (lc->previewstream!=NULL) {
video_preview_stop(lc->previewstream);
lc->previewstream=NULL;
}
if (stream && stream->dir!=SalStreamInactive) {
const char *addr=stream->addr[0]!='\0' ? stream->addr : call->resultdesc->addr;
call->video_profile=make_profile(lc,call->resultdesc,stream,&used_pt);
call->current_params.has_video=FALSE;
if (vstream && vstream->dir!=SalStreamInactive) {
const char *addr=vstream->addr[0]!='\0' ? vstream->addr : call->resultdesc->addr;
call->video_profile=make_profile(call,call->resultdesc,vstream,&used_pt);
if (used_pt!=-1){
VideoStreamDir dir=VideoStreamSendRecv;
MSWebCam *cam=lc->video_conf.device;
bool_t is_inactive=FALSE;
call->params.has_video=TRUE;
call->current_params.has_video=TRUE;
video_stream_set_sent_video_size(call->videostream,linphone_core_get_preferred_video_size(lc));
video_stream_enable_self_view(call->videostream,lc->video_conf.selfview);
@ -880,12 +956,12 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut
video_stream_set_native_preview_window_id (call->videostream,lc->preview_window_id);
video_stream_use_preview_video_window (call->videostream,lc->use_preview_window);
if (stream->dir==SalStreamSendOnly && lc->video_conf.capture ){
if (vstream->dir==SalStreamSendOnly && lc->video_conf.capture ){
cam=get_nowebcam_device();
dir=VideoStreamSendOnly;
}else if (stream->dir==SalStreamRecvOnly && lc->video_conf.display ){
}else if (vstream->dir==SalStreamRecvOnly && lc->video_conf.display ){
dir=VideoStreamRecvOnly;
}else if (stream->dir==SalStreamSendRecv){
}else if (vstream->dir==SalStreamSendRecv){
if (lc->video_conf.display && lc->video_conf.capture)
dir=VideoStreamSendRecv;
else if (lc->video_conf.display)
@ -903,8 +979,8 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut
if (!is_inactive){
video_stream_set_direction (call->videostream, dir);
video_stream_start(call->videostream,
call->video_profile, addr, stream->port,
stream->port+1,
call->video_profile, addr, vstream->port,
vstream->port+1,
used_pt, jitt_comp, cam);
video_stream_set_rtcp_information(call->videostream, cname,tool);
}
@ -939,6 +1015,7 @@ void linphone_call_stop_media_streams(LinphoneCall *call){
video_stream_stop(call->videostream);
call->videostream=NULL;
}
ms_event_queue_skip(call->core->msevq);
#endif
if (call->audio_profile){
@ -953,3 +1030,52 @@ void linphone_call_stop_media_streams(LinphoneCall *call){
}
}
#ifdef VIDEO_ENABLED
/**
* Request remote side to send us VFU.
**/
void linphone_call_send_vfu_request(LinphoneCall *call)
{
if (LinphoneCallStreamsRunning == linphone_call_get_state(call))
sal_call_send_vfu_request(call->op);
}
#endif
void linphone_call_enable_echo_cancellation(LinphoneCall *call, bool_t enable) {
if (call!=NULL && call->audiostream!=NULL && call->audiostream->ec){
bool_t bypass_mode = !enable;
ms_filter_call_method(call->audiostream->ec,MS_ECHO_CANCELLER_SET_BYPASS_MODE,&bypass_mode);
}
}
bool_t linphone_call_echo_cancellation_enabled(LinphoneCall *call) {
if (call!=NULL && call->audiostream!=NULL && call->audiostream->ec){
bool_t val;
ms_filter_call_method(call->audiostream->ec,MS_ECHO_CANCELLER_GET_BYPASS_MODE,&val);
return !val;
} else {
return linphone_core_echo_cancellation_enabled(call->core);
}
}
void linphone_call_enable_echo_limiter(LinphoneCall *call, bool_t val){
if (call!=NULL && call->audiostream!=NULL ) {
if (val) {
const char *type=lp_config_get_string(call->core->config,"sound","el_type","mic");
if (strcasecmp(type,"mic")==0)
audio_stream_enable_echo_limiter(call->audiostream,ELControlMic);
else if (strcasecmp(type,"full")==0)
audio_stream_enable_echo_limiter(call->audiostream,ELControlFull);
} else {
audio_stream_enable_echo_limiter(call->audiostream,ELInactive);
}
}
}
bool_t linphone_call_echo_limiter_enabled(const LinphoneCall *call){
if (call!=NULL && call->audiostream!=NULL ){
return call->audiostream->el_type !=ELInactive ;
} else {
return linphone_core_echo_limiter_enabled(call->core);
}
}

View file

@ -49,6 +49,8 @@ static void toggle_video_preview(LinphoneCore *lc, bool_t val);
#define LOCAL_RING "rings/oldphone.wav"
/* same for remote ring (ringback)*/
#define REMOTE_RING "ringback.wav"
#define HOLD_MUSIC "rings/toy-mono.wav"
extern SalCallbacks linphone_sal_callbacks;
@ -452,6 +454,8 @@ static void sound_config_read(LinphoneCore *lc)
tmpbuf=PACKAGE_SOUND_DIR "/" REMOTE_RING;
}
linphone_core_set_ringback(lc,tmpbuf);
linphone_core_set_play_file(lc,lp_config_get_string(lc->config,"sound","hold_music",PACKAGE_SOUND_DIR "/" HOLD_MUSIC));
check_sound_device(lc);
lc->sound_conf.latency=0;
@ -571,6 +575,7 @@ static void sip_config_read(LinphoneCore *lc)
lc->sip_conf.keepalive_period=lp_config_get_int(lc->config,"sip","keepalive_period",10000);
sal_set_keepalive_period(lc->sal,lc->sip_conf.keepalive_period);
sal_use_one_matching_codec_policy(lc->sal,lp_config_get_int(lc->config,"sip","only_one_codec",0));
sal_use_double_registrations(lc->sal,lp_config_get_int(lc->config,"sip","use_double_registrations",1));
}
static void rtp_config_read(LinphoneCore *lc)
@ -590,6 +595,8 @@ static void rtp_config_read(LinphoneCore *lc)
jitt_comp=lp_config_get_int(lc->config,"rtp","audio_jitt_comp",60);
linphone_core_set_audio_jittcomp(lc,jitt_comp);
jitt_comp=lp_config_get_int(lc->config,"rtp","video_jitt_comp",60);
if (jitt_comp==0) jitt_comp=60;
lc->rtp_conf.video_jitt_comp=jitt_comp;
nortp_timeout=lp_config_get_int(lc->config,"rtp","nortp_timeout",30);
linphone_core_set_nortp_timeout(lc,nortp_timeout);
rtp_no_xmit_on_audio_mute=lp_config_get_int(lc->config,"rtp","rtp_no_xmit_on_audio_mute",FALSE);
@ -816,13 +823,6 @@ static void autoreplier_config_init(LinphoneCore *lc)
*/
void linphone_core_set_download_bandwidth(LinphoneCore *lc, int bw){
lc->net_conf.download_bw=bw;
if (bw==0){ /*infinite*/
lc->dw_audio_bw=-1;
lc->dw_video_bw=-1;
}else {
lc->dw_audio_bw=MIN(lc->audio_bw,bw);
lc->dw_video_bw=MAX(bw-lc->dw_audio_bw-10,0);/*-10: security margin*/
}
}
/**
@ -840,13 +840,6 @@ void linphone_core_set_download_bandwidth(LinphoneCore *lc, int bw){
*/
void linphone_core_set_upload_bandwidth(LinphoneCore *lc, int bw){
lc->net_conf.upload_bw=bw;
if (bw==0){ /*infinite*/
lc->up_audio_bw=-1;
lc->up_video_bw=-1;
}else{
lc->up_audio_bw=MIN(lc->audio_bw,bw);
lc->up_video_bw=MAX(bw-lc->up_audio_bw-10,0);/*-10: security margin*/
}
}
/**
@ -924,7 +917,8 @@ static void linphone_core_init (LinphoneCore * lc, const LinphoneCoreVTable *vta
{
memset (lc, 0, sizeof (LinphoneCore));
lc->data=userdata;
lc->ringstream_autorelease=TRUE;
memcpy(&lc->vtable,vtable,sizeof(LinphoneCoreVTable));
linphone_core_set_state(lc,LinphoneGlobalStartup,"Starting up");
@ -933,8 +927,8 @@ static void linphone_core_init (LinphoneCore * lc, const LinphoneCoreVTable *vta
linphone_core_assign_payload_type(&payload_type_gsm,3,NULL);
linphone_core_assign_payload_type(&payload_type_pcma8000,8,NULL);
linphone_core_assign_payload_type(&payload_type_lpc1015,115,NULL);
linphone_core_assign_payload_type(&payload_type_speex_nb,110,"vbr=vad");
linphone_core_assign_payload_type(&payload_type_speex_wb,111,"vbr=vad");
linphone_core_assign_payload_type(&payload_type_speex_nb,110,"vbr=on");
linphone_core_assign_payload_type(&payload_type_speex_wb,111,"vbr=on");
linphone_core_assign_payload_type(&payload_type_speex_uwb,112,"vbr=on");
linphone_core_assign_payload_type(&payload_type_telephone_event,101,"0-11");
linphone_core_assign_payload_type(&payload_type_ilbc,113,"mode=30");
@ -968,8 +962,8 @@ static void linphone_core_init (LinphoneCore * lc, const LinphoneCoreVTable *vta
linphone_core_assign_payload_type(&payload_type_h263_1998,98,"CIF=1;QCIF=1");
linphone_core_assign_payload_type(&payload_type_mp4v,99,"profile-level-id=3");
linphone_core_assign_payload_type(&payload_type_x_snow,100,NULL);
linphone_core_assign_payload_type(&payload_type_h264,102,NULL);
linphone_core_assign_payload_type(&payload_type_h264,103,"packetization-mode=1");
linphone_core_assign_payload_type(&payload_type_h264,102,"profile-level-id=428014");
linphone_core_assign_payload_type(&payload_type_h264,103,"packetization-mode=1;profile-level-id=428014");
#endif
ms_init();
@ -1630,9 +1624,9 @@ static void linphone_core_do_plugin_tasks(LinphoneCore *lc){
* - handles timers and timeout
* - performs registration to proxies
* - authentication retries
* The application MUST call this function from periodically, in its main loop.
* Be careful that this function must be call from the same thread as
* other liblinphone methods. In not the case make sure all liblinphone calls are
* The application MUST call this function periodically, in its main loop.
* Be careful that this function must be called from the same thread as
* other liblinphone methods. If it is not the case make sure all liblinphone calls are
* serialized with a mutex.
**/
void linphone_core_iterate(LinphoneCore *lc){
@ -1649,6 +1643,19 @@ void linphone_core_iterate(LinphoneCore *lc){
one_second_elapsed=TRUE;
}
if (lc->ecc!=NULL){
LinphoneEcCalibratorStatus ecs=ec_calibrator_get_status(lc->ecc);
if (ecs!=LinphoneEcCalibratorInProgress){
if (lc->ecc->cb)
lc->ecc->cb(lc,ecs,lc->ecc->delay,lc->ecc->cb_data);
if (ecs==LinphoneEcCalibratorDone){
lp_config_set_int(lc->config, "sound", "ec_delay",MAX(lc->ecc->delay-10,0));
}
ec_calibrator_destroy(lc->ecc);
lc->ecc=NULL;
}
}
if (lc->preview_finished){
lc->preview_finished=0;
ring_stop(lc->ringstream);
@ -1656,7 +1663,7 @@ void linphone_core_iterate(LinphoneCore *lc){
lc_callback_obj_invoke(&lc->preview_finished_cb,lc);
}
if (lc->ringstream && lc->dmfs_playing_start_time!=0
if (lc->ringstream && lc->ringstream_autorelease && lc->dmfs_playing_start_time!=0
&& (curtime-lc->dmfs_playing_start_time)>5){
ring_stop(lc->ringstream);
lc->ringstream=NULL;
@ -1664,7 +1671,7 @@ void linphone_core_iterate(LinphoneCore *lc){
}
sal_iterate(lc->sal);
ms_event_queue_pump(lc->msevq);
if (lc->msevq) ms_event_queue_pump(lc->msevq);
if (lc->auto_net_state_mon) monitor_network_state(lc,curtime);
proxy_update(lc);
@ -2169,31 +2176,43 @@ bool_t linphone_core_inc_invite_pending(LinphoneCore*lc){
LinphoneCall *call = linphone_core_get_current_call(lc);
if(call != NULL)
{
if(call->dir==LinphoneCallIncoming)
if(call->dir==LinphoneCallIncoming
&& (call->state == LinphoneCallIncomingReceived || call->state == LinphoneCallIncomingEarlyMedia))
return TRUE;
}
return FALSE;
}
/**
* Updates a running call according to supplied call parameters.
* Updates a running call according to supplied call parameters or parameters changed in the LinphoneCore.
*
* For the moment, this is limited to enabling or disabling the video stream.
* In this version this is limited to the following use cases:
* - setting up/down the video stream according to the video parameter of the LinphoneCallParams (see linphone_call_params_enable_video() ).
* - changing the size of the transmitted video after calling linphone_core_set_preferred_video_size()
*
* In case no changes are requested through the LinphoneCallParams argument, then this argument can be ommitted and set to NULL.
*
* @return 0 if successful, -1 otherwise.
**/
int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, LinphoneCallParams *params){
int err;
if (call->localdesc)
sal_media_description_unref(call->localdesc);
call->params=*params;
call->localdesc=create_local_media_description (lc,call);
call->camera_active=params->has_video;
if (lc->vtable.display_status)
lc->vtable.display_status(lc,_("Modifying call parameters..."));
sal_call_set_local_media_description (call->op,call->localdesc);
err=sal_call_update(call->op);
int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params){
int err=0;
if (params!=NULL){
call->params=*params;
update_local_media_description(lc,call,&call->localdesc);
call->camera_active=params->has_video;
if (lc->vtable.display_status)
lc->vtable.display_status(lc,_("Modifying call parameters..."));
sal_call_set_local_media_description (call->op,call->localdesc);
err=sal_call_update(call->op,"Media parameters update");
}else{
#ifdef VIDEO_ENABLED
if (call->videostream!=NULL){
video_stream_set_sent_video_size(call->videostream,linphone_core_get_preferred_video_size(lc));
video_stream_update_video_params (call->videostream);
}
#endif
}
return err;
}
@ -2213,7 +2232,7 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, LinphoneCall
**/
int linphone_core_accept_call(LinphoneCore *lc, LinphoneCall *call)
{
LinphoneProxyConfig *cfg=NULL;
LinphoneProxyConfig *cfg=NULL,*dest_proxy=NULL;
const char *contact=NULL;
SalOp *replaced;
SalMediaDescription *new_md;
@ -2268,8 +2287,15 @@ int linphone_core_accept_call(LinphoneCore *lc, LinphoneCall *call)
}
linphone_core_get_default_proxy(lc,&cfg);
dest_proxy=cfg;
dest_proxy=linphone_core_lookup_known_proxy(lc,call->log->to);
if (cfg!=dest_proxy && dest_proxy!=NULL) {
ms_message("Overriding default proxy setting for this call:");
ms_message("The used identity will be %s",linphone_proxy_config_get_identity(dest_proxy));
}
/*try to be best-effort in giving real local or routable contact address*/
contact=get_fixed_contact(lc,call,cfg);
contact=get_fixed_contact(lc,call,dest_proxy);
if (contact)
sal_op_set_contact(call->op,contact);
@ -2404,13 +2430,23 @@ LinphoneCall *linphone_core_get_current_call(const LinphoneCore *lc)
int linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *the_call)
{
LinphoneCall *call = the_call;
const char *subject=NULL;
if (call->state!=LinphoneCallStreamsRunning && call->state!=LinphoneCallPausedByRemote){
ms_warning("Cannot pause this call, it is not active.");
return -1;
}
if (sal_call_hold(call->op,TRUE) != 0)
if (sal_media_description_has_dir(call->resultdesc,SalStreamSendRecv)){
sal_media_description_set_dir(call->localdesc,SalStreamSendOnly);
subject="Call on hold";
}else if (sal_media_description_has_dir(call->resultdesc,SalStreamRecvOnly)){
sal_media_description_set_dir(call->localdesc,SalStreamSendOnly);
subject="Call on hold for me too";
}else{
ms_error("No reason to pause this call, it is already paused or inactive.");
return -1;
}
if (sal_call_update(call->op,subject) != 0)
{
if (lc->vtable.display_warning)
lc->vtable.display_warning(lc,_("Could not pause the call"));
@ -2460,14 +2496,14 @@ int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *the_call)
return -1;
}
ms_message("Resuming call %p",call);
if(sal_call_hold(call->op,FALSE) != 0){
sal_media_description_set_dir(call->localdesc,SalStreamSendRecv);
if(sal_call_update(call->op,"Call resuming") != 0){
return -1;
}
linphone_call_set_state (call,LinphoneCallResuming,"Resuming");
snprintf(temp,sizeof(temp)-1,"Resuming the call with %s",linphone_call_get_remote_address_as_string(call));
if (lc->vtable.display_status)
lc->vtable.display_status(lc,temp);
lc->current_call=call;
return 0;
}
@ -2828,8 +2864,10 @@ void linphone_core_set_sound_source(LinphoneCore *lc, char source)
void linphone_core_set_ring(LinphoneCore *lc,const char *path){
if (lc->sound_conf.local_ring!=0){
ms_free(lc->sound_conf.local_ring);
lc->sound_conf.local_ring=NULL;
}
lc->sound_conf.local_ring=ms_strdup(path);
if (path)
lc->sound_conf.local_ring=ms_strdup(path);
if ( linphone_core_ready(lc) && lc->sound_conf.local_ring)
lp_config_set_string(lc->config,"sound","local_ring",lc->sound_conf.local_ring);
}
@ -2843,7 +2881,7 @@ const char *linphone_core_get_ring(const LinphoneCore *lc){
return lc->sound_conf.local_ring;
}
static void notify_end_of_ring(void *ud ,unsigned int event, void * arg){
static void notify_end_of_ring(void *ud, MSFilter *f, unsigned int event, void *arg){
LinphoneCore *lc=(LinphoneCore*)ud;
lc->preview_finished=1;
}
@ -2888,7 +2926,7 @@ const char * linphone_core_get_ringback(const LinphoneCore *lc){
}
/**
* Enables or disable echo cancellation.
* Enables or disable echo cancellation. Value is saved an used for subsequent calls
*
* @ingroup media_parameters
**/
@ -2898,6 +2936,7 @@ void linphone_core_enable_echo_cancellation(LinphoneCore *lc, bool_t val){
lp_config_set_int(lc->config,"sound","echocancellation",val);
}
/**
* Returns TRUE if echo cancellation is enabled.
*
@ -3363,12 +3402,18 @@ void linphone_core_use_preview_window(LinphoneCore *lc, bool_t yesno){
}
static MSVideoSizeDef supported_resolutions[]={
#ifdef ENABLE_HD
{ {MS_VIDEO_SIZE_1080P_W,MS_VIDEO_SIZE_1080P_H} , "1080p" },
{ {MS_VIDEO_SIZE_720P_W,MS_VIDEO_SIZE_720P_H} , "1080p" },
#endif
{ {MS_VIDEO_SIZE_SVGA_W,MS_VIDEO_SIZE_SVGA_H} , "svga" },
{ {MS_VIDEO_SIZE_4CIF_W,MS_VIDEO_SIZE_4CIF_H} , "4cif" },
{ {MS_VIDEO_SIZE_VGA_W,MS_VIDEO_SIZE_VGA_H} , "vga" },
{ {MS_VIDEO_SIZE_CIF_W,MS_VIDEO_SIZE_CIF_H} , "cif" },
{ {MS_VIDEO_SIZE_QVGA_W,MS_VIDEO_SIZE_QVGA_H} , "qvga" },
{ {MS_VIDEO_SIZE_QVGA_H,MS_VIDEO_SIZE_QVGA_W} , "qvga-portrait" },
{ {MS_VIDEO_SIZE_QCIF_W,MS_VIDEO_SIZE_QCIF_H} , "qcif" },
{ {MS_VIDEO_SIZE_QCIF_H,MS_VIDEO_SIZE_QCIF_W} , "qcif-portrait" },
{ {0,0} , NULL }
};
@ -3509,8 +3554,10 @@ static MSFilter *get_dtmf_gen(LinphoneCore *lc){
}
}
if (lc->ringstream==NULL){
float amp=0.1;
MSSndCard *ringcard=lc->sound_conf.lsd_card ?lc->sound_conf.lsd_card : lc->sound_conf.ring_sndcard;
lc->ringstream=ring_start(NULL,0,ringcard);
ms_filter_call_method(lc->ringstream->gendtmf,MS_DTMF_GEN_SET_DEFAULT_AMPLITUDE,&amp);
lc->dmfs_playing_start_time=time(NULL);
}else{
if (lc->dmfs_playing_start_time!=0)
@ -3667,17 +3714,16 @@ void sip_config_uninit(LinphoneCore *lc)
linphone_proxy_config_write_to_config_file(lc->config,cfg,i);
linphone_proxy_config_edit(cfg); /* to unregister */
}
/*to ensure remove configs are erased:*/
linphone_proxy_config_write_to_config_file(lc->config,NULL,i);
if (lc->sal){
int i;
for (i=0;i<20;i++){
sal_iterate(lc->sal);
for (i=0;i<20;i++){
sal_iterate(lc->sal);
#ifndef WIN32
usleep(100000);
usleep(100000);
#else
Sleep(100);
Sleep(100);
#endif
}
}
ms_list_for_each(config->proxies,(void (*)(void*)) linphone_proxy_config_destroy);
@ -3809,7 +3855,6 @@ static void linphone_core_uninit(LinphoneCore *lc)
usleep(50000);
#endif
}
if (lc->friends)
ms_list_for_each(lc->friends,(void (*)(void *))linphone_friend_close_subscriptions);
linphone_core_set_state(lc,LinphoneGlobalShutdown,"Shutting down");
@ -3820,14 +3865,16 @@ static void linphone_core_uninit(LinphoneCore *lc)
}
#endif
ms_event_queue_destroy(lc->msevq);
lc->msevq=NULL;
/* save all config */
net_config_uninit(lc);
sip_config_uninit(lc);
rtp_config_uninit(lc);
if (lc->ringstream) ring_stop(lc->ringstream);
sound_config_uninit(lc);
video_config_uninit(lc);
codecs_config_uninit(lc);
ui_config_uninit(lc);
sip_config_uninit(lc);
if (lp_config_needs_commit(lc->config)) lp_config_sync(lc->config);
lp_config_destroy(lc->config);
lc->config = NULL; /* Mark the config as NULL to block further calls */
@ -3837,7 +3884,6 @@ static void linphone_core_uninit(LinphoneCore *lc)
lc->call_logs=ms_list_free(lc->call_logs);
linphone_core_free_payload_types();
ortp_exit();
linphone_core_set_state(lc,LinphoneGlobalOff,"Off");
}
@ -3959,7 +4005,7 @@ static PayloadType* find_payload_type_from_list(const char* type, int rate,const
const MSList *elem;
for(elem=from;elem!=NULL;elem=elem->next){
PayloadType *pt=(PayloadType*)elem->data;
if ((strcmp((char*)type, payload_type_get_mime(pt)) == 0) && rate==pt->clock_rate) {
if ((strcmp((char*)type, payload_type_get_mime(pt)) == 0) && (rate == -1 || rate==pt->clock_rate)) {
return pt;
}
}
@ -4027,4 +4073,31 @@ const char *linphone_error_to_string(LinphoneReason err){
}
return "unknown error";
}
/**
* enable signaling keep alive
*/
void linphone_core_enable_keep_alive(LinphoneCore* lc,bool_t enable) {
if (enable > 0) {
sal_set_keepalive_period(lc->sal,lc->sip_conf.keepalive_period);
} else {
sal_set_keepalive_period(lc->sal,0);
}
}
/**
* Is signaling keep alive
*/
bool_t linphone_core_keep_alive_enabled(LinphoneCore* lc) {
return sal_get_keepalive_period(lc->sal) > 0;
}
void linphone_core_start_dtmf_stream(LinphoneCore* lc) {
get_dtmf_gen(lc); /*make sure ring stream is started*/
lc->ringstream_autorelease=FALSE; /*disable autorelease mode*/
}
void linphone_core_stop_dtmf_stream(LinphoneCore* lc) {
if (lc->ringstream) ring_stop(lc->ringstream);
lc->ringstream=NULL;
}

View file

@ -185,6 +185,7 @@ void linphone_call_params_destroy(LinphoneCallParams *cp);
/**
* Enum describing failure reasons.
* @ingroup initializing
**/
enum _LinphoneReason{
LinphoneReasonNone,
@ -203,8 +204,13 @@ const char *linphone_reason_to_string(LinphoneReason err);
struct _LinphoneCall;
typedef struct _LinphoneCall LinphoneCall;
/**
* LinphoneCallState enum represents the different state a call can reach into.
* The application is notified of state changes through the LinphoneCoreVTable::call_state_changed callback.
* @ingroup call_control
**/
typedef enum _LinphoneCallState{
LinphoneCallIdle,
LinphoneCallIdle, /**<Initial call state */
LinphoneCallIncomingReceived, /**<This is a new incoming call */
LinphoneCallOutgoingInit, /**<An outgoing call is started */
LinphoneCallOutgoingProgress, /**<An outgoing call is in progress */
@ -221,7 +227,8 @@ typedef enum _LinphoneCallState{
LinphoneCallPausedByRemote, /**<The call is paused by remote end*/
LinphoneCallUpdatedByRemote, /**<The call's parameters are updated, used for example when video is asked by remote */
LinphoneCallIncomingEarlyMedia, /**<We are proposing early media to an incoming call */
LinphoneCallUpdated /**<The remote accepted the call update initiated by us */
LinphoneCallUpdated, /**<The remote accepted the call update initiated by us */
LinphoneCallReleased /**< The call object is no more retained by the core */
} LinphoneCallState;
const char *linphone_call_state_to_string(LinphoneCallState cs);
@ -238,6 +245,7 @@ void linphone_call_unref(LinphoneCall *call);
LinphoneCallLog *linphone_call_get_call_log(const LinphoneCall *call);
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);
void linphone_call_enable_camera(LinphoneCall *lc, bool_t enabled);
@ -247,8 +255,34 @@ LinphoneReason linphone_call_get_reason(const LinphoneCall *call);
const char *linphone_call_get_remote_user_agent(LinphoneCall *call);
void *linphone_call_get_user_pointer(LinphoneCall *call);
void linphone_call_set_user_pointer(LinphoneCall *call, void *user_pointer);
/**
* Enables or disable echo cancellation for this call
* @param call
* @param val
*
* @ingroup media_parameters
**/
void linphone_call_enable_echo_cancellation(LinphoneCall *call, bool_t val) ;
/**
* Returns TRUE if echo cancellation is enabled.
*
* @ingroup media_parameters
**/
bool_t linphone_call_echo_cancellation_enabled(LinphoneCall *lc);
/**
* Enables or disable echo limiter for this call
* @param call
* @param val
*
* @ingroup media_parameters
**/
void linphone_call_enable_echo_limiter(LinphoneCall *call, bool_t val);
/**
* Returns TRUE if echo limiter is enabled.
*
* @ingroup media_parameters
**/
bool_t linphone_call_echo_limiter_enabled(const LinphoneCall *call);
/**
* @addtogroup proxies
* @{
@ -275,11 +309,11 @@ typedef struct _LinphoneProxyConfig LinphoneProxyConfig;
* LinphoneRegistrationState describes proxy registration states.
**/
typedef enum _LinphoneRegistrationState{
LinphoneRegistrationNone,
LinphoneRegistrationProgress,
LinphoneRegistrationOk,
LinphoneRegistrationCleared,
LinphoneRegistrationFailed
LinphoneRegistrationNone, /**<Initial state for registrations */
LinphoneRegistrationProgress, /**<Registration is in progress */
LinphoneRegistrationOk, /**< Registration is successful */
LinphoneRegistrationCleared, /**< Unregistration succeeded */
LinphoneRegistrationFailed /**<Registration failed */
}LinphoneRegistrationState;
/**
@ -303,6 +337,13 @@ void linphone_proxy_config_enable_register(LinphoneProxyConfig *obj, bool_t val)
#define linphone_proxy_config_enableregister linphone_proxy_config_enable_register
void linphone_proxy_config_edit(LinphoneProxyConfig *obj);
int linphone_proxy_config_done(LinphoneProxyConfig *obj);
/**
* Indicates either or not, PUBLISH must be issued for this #LinphoneProxyConfig .
* <br> In case this #LinphoneProxyConfig has been added to #LinphoneCore, follows the linphone_proxy_config_edit() rule.
* @param obj object pointer
* @param val if true, publish will be engaged
*
*/
void linphone_proxy_config_enable_publish(LinphoneProxyConfig *obj, bool_t val);
void linphone_proxy_config_set_dial_escape_plus(LinphoneProxyConfig *cfg, bool_t val);
void linphone_proxy_config_set_dial_prefix(LinphoneProxyConfig *cfg, const char *prefix);
@ -451,6 +492,17 @@ void * linphone_chat_room_get_user_data(LinphoneChatRoom *cr);
/**
* @}
*/
/**
* @addtogroup initializing
* @{
**/
/**
* LinphoneGlobalState describes the global state of the LinphoneCore object.
* It is notified via the LinphoneCoreVTable::global_state_changed
**/
typedef enum _LinphoneGlobalState{
LinphoneGlobalOff,
LinphoneGlobalStartup,
@ -460,11 +512,6 @@ typedef enum _LinphoneGlobalState{
const char *linphone_global_state_to_string(LinphoneGlobalState gs);
/**
* @addtogroup initializing
* @{
**/
/**Call state notification callback prototype*/
typedef void (*LinphoneGlobalStateCb)(struct _LinphoneCore *lc, LinphoneGlobalState gstate, const char *message);
@ -618,7 +665,7 @@ int linphone_core_pause_all_calls(LinphoneCore *lc);
int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *call);
int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, LinphoneCallParams *params);
int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params);
LinphoneCallParams *linphone_core_create_default_call_parameters(LinphoneCore *lc);
@ -886,6 +933,14 @@ void linphone_core_set_network_reachable(LinphoneCore* lc,bool_t value);
*/
bool_t linphone_core_is_network_reachabled(LinphoneCore* lc);
/**
* enable signaling keep alive. small udp packet sent periodically to keep udp NAT association
*/
void linphone_core_enable_keep_alive(LinphoneCore* lc,bool_t enable);
/**
* Is signaling keep alive
*/
bool_t linphone_core_keep_alive_enabled(LinphoneCore* lc);
void *linphone_core_get_user_data(LinphoneCore *lc);
@ -922,6 +977,6 @@ LinphoneGlobalState linphone_core_get_global_state(const LinphoneCore *lc);
}
#endif
void linphone_call_send_vfu_request(LinphoneCall *call);
#endif

View file

@ -17,15 +17,16 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <jni.h>
#include "linphonecore.h"
#include "linphonecore_utils.h"
#include "mediastreamer2/msjava.h"
#ifdef ANDROID
#include <android/log.h>
extern "C" void libmsilbc_init();
extern "C" void libmsx264_init();
#endif /*ANDROID*/
extern "C" void ms_andsnd_set_jvm(JavaVM *jvm) ;
extern "C" void ms_andvid_set_jvm(JavaVM *jvm) ;
static JavaVM *jvm=0;
#ifdef ANDROID
@ -46,10 +47,7 @@ static void linphone_android_log_handler(OrtpLogLevel lev, const char *fmt, va_l
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *ajvm, void *reserved)
{
#ifdef ANDROID
ms_andsnd_set_jvm(ajvm);
#ifdef VIDEO_ENABLED
ms_andvid_set_jvm(ajvm);
#endif /*VIDEO_ENABLED*/
ms_set_jvm(ajvm);
#endif /*ANDROID*/
jvm=ajvm;
return JNI_VERSION_1_2;
@ -103,7 +101,10 @@ public:
callStateId = env->GetMethodID(listernerClass,"callState","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCall;Lorg/linphone/core/LinphoneCall$State;Ljava/lang/String;)V");
callStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCall$State"));
callStateFromIntId = env->GetStaticMethodID(callStateClass,"fromInt","(I)Lorg/linphone/core/LinphoneCall$State;");
/*void ecCalibrationStatus(LinphoneCore.EcCalibratorStatus status, int delay_ms, Object data);*/
ecCalibrationStatusId = env->GetMethodID(listernerClass,"ecCalibrationStatus","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCore$EcCalibratorStatus;ILjava/lang/Object;)V");
ecCalibratorStatusClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCore$EcCalibratorStatus"));
ecCalibratorStatusFromIntId = env->GetStaticMethodID(ecCalibratorStatusClass,"fromInt","(I)Lorg/linphone/core/LinphoneCore$EcCalibratorStatus;");
/*void newSubscriptionRequest(LinphoneCore lc, LinphoneFriend lf, String url)*/
newSubscriptionRequestId = env->GetMethodID(listernerClass,"newSubscriptionRequest","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneFriend;Ljava/lang/String;)V");
@ -168,6 +169,10 @@ public:
jmethodID callStateId;
jmethodID callStateFromIntId;
jclass ecCalibratorStatusClass;
jmethodID ecCalibrationStatusId;
jmethodID ecCalibratorStatusFromIntId;
jclass proxyClass;
jmethodID proxyCtrId;
@ -293,6 +298,26 @@ public:
,env->NewObject(lcData->addressClass,lcData->addressCtrId,(jlong)from)
,message ? env->NewStringUTF(message) : NULL);
}
static void ecCalibrationStatus(LinphoneCore *lc, LinphoneEcCalibratorStatus status, int delay_ms, void *data) {
JNIEnv *env = 0;
jint result = jvm->AttachCurrentThread(&env,NULL);
if (result != 0) {
ms_error("cannot attach VM\n");
return;
}
LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_get_user_data(lc);
env->CallVoidMethod(lcData->listener
,lcData->ecCalibrationStatusId
,lcData->core
,env->CallStaticObjectMethod(lcData->ecCalibratorStatusClass,lcData->ecCalibratorStatusFromIntId,(jint)status)
,delay_ms
,data ? data : NULL);
if (data != NULL &&status !=LinphoneEcCalibratorInProgress ) {
//final state, releasing global ref
env->DeleteGlobalRef((jobject)data);
}
}
};
@ -306,12 +331,12 @@ extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_newLinphoneCore(JNIEnv*
const char* userConfig = juserConfig?env->GetStringUTFChars(juserConfig, NULL):NULL;
const char* factoryConfig = jfactoryConfig?env->GetStringUTFChars(jfactoryConfig, NULL):NULL;
LinphoneCoreData* ldata = new LinphoneCoreData(env,thiz,jlistener,juserdata);
#ifdef ANDROID
ms_andsnd_set_jvm(jvm);
#endif /*ANDROID*/
#ifdef HAVE_ILBC
libmsilbc_init(); // requires an fpu
#endif
#ifdef VIDEO_ENABLED
libmsx264_init();
#endif
jlong nativePtr = (jlong)linphone_core_new( &ldata->vTable
,userConfig
@ -512,6 +537,24 @@ extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_findPayloadType(JNIEnv*
env->ReleaseStringUTFChars(jmime, mime);
return result;
}
extern "C" jlongArray Java_org_linphone_core_LinphoneCoreImpl_listVideoPayloadTypes(JNIEnv* env
,jobject thiz
,jlong lc) {
const MSList* codecs = linphone_core_get_video_codecs((LinphoneCore*)lc);
int codecsCount = ms_list_size(codecs);
jlongArray jCodecs = env->NewLongArray(codecsCount);
jlong *jInternalArray = env->GetLongArrayElements(jCodecs, NULL);
for (int i = 0; i < codecsCount; i++ ) {
jInternalArray[i] = (unsigned long) (codecs->data);
codecs = codecs->next;
}
env->ReleaseLongArrayElements(jCodecs, jInternalArray, 0);
return jCodecs;
}
extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_enablePayloadType(JNIEnv* env
,jobject thiz
,jlong lc
@ -599,6 +642,29 @@ extern "C" jstring Java_org_linphone_core_LinphoneCoreImpl_getRing(JNIEnv* env
return NULL;
}
}
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_enableKeepAlive(JNIEnv* env
,jobject thiz
,jlong lc
,jboolean enable) {
linphone_core_enable_keep_alive((LinphoneCore*)lc,enable);
}
extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_isKeepAliveEnabled(JNIEnv* env
,jobject thiz
,jlong lc) {
return linphone_core_keep_alive_enabled((LinphoneCore*)lc);
}
extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_startEchoCalibration(JNIEnv* env
,jobject thiz
,jlong lc
,jobject data) {
return linphone_core_start_echo_calibration((LinphoneCore*)lc
, LinphoneCoreData::ecCalibrationStatus
, data?env->NewGlobalRef(data):NULL);
}
//ProxyConfig
@ -710,7 +776,15 @@ extern "C" void Java_org_linphone_core_LinphoneProxyConfigImpl_setDialPrefix(JNI
linphone_proxy_config_set_dial_prefix((LinphoneProxyConfig*)proxyCfg,prefix);
env->ReleaseStringUTFChars(jprefix, prefix);
}
extern "C" void Java_org_linphone_core_LinphoneProxyConfigImpl_enablePublish(JNIEnv* env
,jobject thiz
,jlong proxyCfg
,jboolean val) {
linphone_proxy_config_enable_publish((LinphoneProxyConfig*)proxyCfg,val);
}
extern "C" jboolean Java_org_linphone_core_LinphoneProxyConfigImpl_publishEnabled(JNIEnv* env,jobject thiz,jlong proxyCfg) {
return linphone_proxy_config_publish_enabled((LinphoneProxyConfig*)proxyCfg);
}
//Auth Info
@ -834,12 +908,10 @@ extern "C" jboolean Java_org_linphone_core_LinphoneCallLogImpl_isIncoming(JNIEnv
return ((LinphoneCallLog*)ptr)->dir==LinphoneCallIncoming?JNI_TRUE:JNI_FALSE;
}
extern "C" jstring Java_org_linphone_core_PayloadTypeImpl_toString(JNIEnv* env
,jobject thiz
,jlong ptr) {
/*payloadType*/
extern "C" jstring Java_org_linphone_core_PayloadTypeImpl_toString(JNIEnv* env,jobject thiz,jlong ptr) {
PayloadType* pt = (PayloadType*)ptr;
char* value = ms_strdup_printf("[%s] clock [%s], bitrate [%s]"
char* value = ms_strdup_printf("[%s] clock [%i], bitrate [%i]"
,payload_type_get_mime(pt)
,payload_type_get_rate(pt)
,payload_type_get_bitrate(pt));
@ -847,6 +919,16 @@ extern "C" jstring Java_org_linphone_core_PayloadTypeImpl_toString(JNIEnv* env
ms_free(value);
return jvalue;
}
extern "C" jstring Java_org_linphone_core_PayloadTypeImpl_getMime(JNIEnv* env,jobject thiz,jlong ptr) {
PayloadType* pt = (PayloadType*)ptr;
jstring jvalue =env->NewStringUTF(payload_type_get_mime(pt));
return jvalue;
}
extern "C" jint Java_org_linphone_core_PayloadTypeImpl_getRate(JNIEnv* env,jobject thiz, jlong ptr) {
PayloadType* pt = (PayloadType*)ptr;
return payload_type_get_rate(pt);
}
//LinphoneCall
extern "C" void Java_org_linphone_core_LinphoneCallImpl_ref(JNIEnv* env
,jobject thiz
@ -883,6 +965,36 @@ extern "C" jint Java_org_linphone_core_LinphoneCallImpl_getState( JNIEnv* env
,jlong ptr) {
return (jint)linphone_call_get_state((LinphoneCall*)ptr);
}
extern "C" void Java_org_linphone_core_LinphoneCallImpl_enableEchoCancellation( JNIEnv* env
,jobject thiz
,jlong ptr
,jboolean value) {
linphone_call_enable_echo_cancellation((LinphoneCall*)ptr,value);
}
extern "C" jboolean Java_org_linphone_core_LinphoneCallImpl_isEchoCancellationEnabled( JNIEnv* env
,jobject thiz
,jlong ptr) {
return linphone_call_echo_cancellation_enabled((LinphoneCall*)ptr);
}
extern "C" void Java_org_linphone_core_LinphoneCallImpl_enableEchoLimiter( JNIEnv* env
,jobject thiz
,jlong ptr
,jboolean value) {
linphone_call_enable_echo_limiter((LinphoneCall*)ptr,value);
}
extern "C" jboolean Java_org_linphone_core_LinphoneCallImpl_isEchoLimiterEnabled( JNIEnv* env
,jobject thiz
,jlong ptr) {
return linphone_call_echo_limiter_enabled((LinphoneCall*)ptr);
}
extern "C" jlong Java_org_linphone_core_LinphoneCallImpl_getReplacedCall( JNIEnv* env
,jobject thiz
,jlong ptr) {
return (jlong)linphone_call_get_replaced_call((LinphoneCall*)ptr);
}
//LinphoneFriend
extern "C" long Java_org_linphone_core_LinphoneFriendImpl_newLinphoneFriend(JNIEnv* env
@ -993,6 +1105,10 @@ extern "C" jstring Java_org_linphone_core_LinphoneCoreImpl_getStunServer(JNIEnv
return jvalue;
}
extern "C" void Java_org_linphone_core_LinphoneCallParamsImpl_audioBandwidth(JNIEnv *env, jobject thiz, jlong lcp, jint bw){
linphone_call_params_set_audio_bandwidth_limit((LinphoneCallParams*)lcp, bw);
}
extern "C" void Java_org_linphone_core_LinphoneCallParamsImpl_enableVideo(JNIEnv *env, jobject thiz, jlong lcp, jboolean b){
linphone_call_params_enable_video((LinphoneCallParams*)lcp, b);
}
@ -1000,15 +1116,19 @@ extern "C" void Java_org_linphone_core_LinphoneCallParamsImpl_enableVideo(JNIEnv
extern "C" jboolean Java_org_linphone_core_LinphoneCallParamsImpl_getVideoEnabled(JNIEnv *env, jobject thiz, jlong lcp){
return linphone_call_params_video_enabled((LinphoneCallParams*)lcp);
}
extern "C" jlong Java_org_linphone_core_LinphoneCallParamsImpl_copy(JNIEnv *env, jobject thiz, jlong lcp){
return (jlong) linphone_call_params_copy((LinphoneCallParams*)lcp);
extern "C" void Java_org_linphone_core_LinphoneCallParamsImpl_destroy(JNIEnv *env, jobject thiz, jlong lc){
return linphone_call_params_destroy((LinphoneCallParams*)lc);
}
extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_createDefaultCallParams(JNIEnv *env, jobject thiz, jlong lc){
return (jlong) linphone_core_create_default_call_parameters((LinphoneCore*)lc);
}
extern "C" jlong Java_org_linphone_core_LinphoneCallImpl_getCurrentParams(JNIEnv *env, jobject thiz, jlong lc){
return (jlong) linphone_call_get_current_params((LinphoneCall*)lc);
extern "C" jlong Java_org_linphone_core_LinphoneCallImpl_getCurrentParamsCopy(JNIEnv *env, jobject thiz, jlong lc){
return (jlong) linphone_call_params_copy(linphone_call_get_current_params((LinphoneCall*)lc));
}
extern "C" jlong Java_org_linphone_core_LinphoneCallImpl_enableCamera(JNIEnv *env, jobject thiz, jlong lc, jboolean b){
linphone_call_enable_camera((LinphoneCall *)lc, (bool_t) b);
}
extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_inviteAddressWithParams(JNIEnv *env, jobject thiz, jlong lc, jlong addr, jlong params){
@ -1020,7 +1140,7 @@ extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_updateAddressWithParams(
}
extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_updateCall(JNIEnv *env, jobject thiz, jlong lc, jlong call, jlong params){
return (jint) linphone_core_update_call((LinphoneCore *)lc, (LinphoneCall *)call, (LinphoneCallParams *)params);
return (jint) linphone_core_update_call((LinphoneCore *)lc, (LinphoneCall *)call, (const LinphoneCallParams *)params);
}
@ -1046,4 +1166,10 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setDownloadBandwidth(JNI
extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setUploadBandwidth(JNIEnv *env, jobject thiz, jlong lc, jint bw){
linphone_core_set_upload_bandwidth((LinphoneCore *)lc, (int) bw);
}
extern "C" int Java_org_linphone_core_LinphoneProxyConfigImpl_getState(JNIEnv* env,jobject thiz,jlong ptr) {
return (int) linphone_proxy_config_get_state((const LinphoneProxyConfig *) ptr);
}
extern "C" void Java_org_linphone_core_LinphoneProxyConfigImpl_setExpires(JNIEnv* env,jobject thiz,jlong ptr,jint delay) {
linphone_proxy_config_expires((LinphoneProxyConfig *) ptr, (int) delay);
}

View file

@ -25,6 +25,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#else
#include "linphone/linphonecore.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef struct _LsdPlayer LsdPlayer;
typedef struct _LinphoneSoundDaemon LinphoneSoundDaemon;
@ -49,4 +52,35 @@ void linphone_sound_daemon_release_all_players(LinphoneSoundDaemon *obj);
void linphone_core_use_sound_daemon(LinphoneCore *lc, LinphoneSoundDaemon *lsd);
void linphone_sound_daemon_destroy(LinphoneSoundDaemon *obj);
/**
* Enum describing the result of the echo canceller calibration process.
**/
typedef enum {
LinphoneEcCalibratorInProgress,
LinphoneEcCalibratorDone,
LinphoneEcCalibratorFailed
}LinphoneEcCalibratorStatus;
typedef void (*LinphoneEcCalibrationCallback)(LinphoneCore *lc, LinphoneEcCalibratorStatus status, int delay_ms, 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);
#if TARGET_OS_IPHONE
/**
* IOS special function to warm up dtmf feeback stream. #linphone_core_stop_dtmf_stream must be called before entering BG mode
*/
void linphone_core_start_dtmf_stream(const LinphoneCore* lc);
/**
* IOS special function to stop dtmf feed back function. Must be called before entering BG mode
*/
void linphone_core_stop_dtmf_stream(const LinphoneCore* lc);
#endif
#ifdef __cplusplus
}
#endif
#endif

View file

@ -156,7 +156,7 @@ void *lsd_player_get_user_pointer(const LsdPlayer *p){
return p->user_data;
}
static void lsd_player_on_eop(void * userdata, unsigned int id, void *arg){
static void lsd_player_on_eop(void * userdata, MSFilter *f, unsigned int id, void *arg){
LsdPlayer *p=(LsdPlayer *)userdata;
if (p->eop_cb!=NULL)
p->eop_cb(p);

View file

@ -233,11 +233,9 @@ static double get_audio_payload_bandwidth(LinphoneCore *lc, const PayloadType *p
return packet_size*8.0*npacket;
}
void linphone_core_update_allocated_audio_bandwidth_in_call(LinphoneCore *lc, const PayloadType *pt){
lc->audio_bw=(int)(get_audio_payload_bandwidth(lc,pt)/1000.0);
/*update*/
linphone_core_set_download_bandwidth(lc,lc->net_conf.download_bw);
linphone_core_set_upload_bandwidth(lc,lc->net_conf.upload_bw);
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);
ms_message("Audio bandwidth for this call is %i",call->audio_bw);
}
void linphone_core_update_allocated_audio_bandwidth(LinphoneCore *lc){
@ -254,7 +252,7 @@ void linphone_core_update_allocated_audio_bandwidth(LinphoneCore *lc){
}
}
if (max) {
linphone_core_update_allocated_audio_bandwidth_in_call(lc,max);
lc->audio_bw=(int)(get_audio_payload_bandwidth(lc,max)/1000.0);
}
}
@ -278,11 +276,6 @@ bool_t linphone_core_is_payload_type_usable_for_bandwidth(LinphoneCore *lc, Payl
break;
case PAYLOAD_VIDEO:
if (bandwidth_limit!=0) {/* infinite (-1) or strictly positive*/
/*let the video use all the bandwidth minus the maximum bandwidth used by audio */
if (bandwidth_limit>0)
pt->normal_bitrate=bandwidth_limit*1000;
else
pt->normal_bitrate=1500000; /*around 1.5 Mbit/s*/
ret=TRUE;
}
else ret=FALSE;
@ -295,27 +288,25 @@ bool_t linphone_core_is_payload_type_usable_for_bandwidth(LinphoneCore *lc, Payl
bool_t linphone_core_check_payload_type_usability(LinphoneCore *lc, PayloadType *pt)
{
double codec_band;
int min_audio_bw;
int min_video_bw;
int allowed_bw,video_bw;
bool_t ret=FALSE;
/*
update allocated audio bandwidth to allocate the remaining to video.
This must be done outside calls, because after sdp negociation
the audio bandwidth is refined to the selected codec
*/
if (!linphone_core_in_call(lc)) linphone_core_update_allocated_audio_bandwidth(lc);
min_audio_bw=get_min_bandwidth(linphone_core_get_download_bandwidth(lc),
linphone_core_update_allocated_audio_bandwidth(lc);
allowed_bw=get_min_bandwidth(linphone_core_get_download_bandwidth(lc),
linphone_core_get_upload_bandwidth(lc));
if (min_audio_bw==0) min_audio_bw=-1;
min_video_bw=get_min_bandwidth(lc->dw_video_bw,lc->up_video_bw);
if (allowed_bw==0) {
allowed_bw=-1;
video_bw=1500; /*around 1.5 Mbit/s*/
}else
video_bw=get_video_bandwidth(allowed_bw,lc->audio_bw);
switch (pt->type){
case PAYLOAD_AUDIO_CONTINUOUS:
case PAYLOAD_AUDIO_PACKETIZED:
codec_band=get_audio_payload_bandwidth(lc,pt);
ret=bandwidth_is_greater(min_audio_bw*1000,codec_band);
ret=bandwidth_is_greater(allowed_bw*1000,codec_band);
/*hack to avoid using uwb codecs when having low bitrate and video*/
if (bandwidth_is_greater(199,min_audio_bw)){
if (bandwidth_is_greater(199,allowed_bw)){
if (linphone_core_video_enabled(lc) && pt->clock_rate>16000){
ret=FALSE;
}
@ -323,19 +314,13 @@ bool_t linphone_core_check_payload_type_usability(LinphoneCore *lc, PayloadType
//ms_message("Payload %s: %g",pt->mime_type,codec_band);
break;
case PAYLOAD_VIDEO:
if (min_video_bw!=0) {/* infinite (-1) or strictly positive*/
/*let the video use all the bandwidth minus the maximum bandwidth used by audio */
if (min_video_bw>0)
pt->normal_bitrate=min_video_bw*1000;
else
pt->normal_bitrate=1500000; /*around 1.5 Mbit/s*/
if (video_bw>0){
pt->normal_bitrate=video_bw*1000;
ret=TRUE;
}
else ret=FALSE;
break;
}
/*if (!ret) ms_warning("Payload %s is not usable with your internet connection.",pt->mime_type);*/
return ret;
}

View file

@ -109,7 +109,7 @@ static MSList *match_payloads(const MSList *local, const MSList *remote, bool_t
static SalStreamDir compute_dir(SalStreamDir local, SalStreamDir answered){
static SalStreamDir compute_dir_outgoing(SalStreamDir local, SalStreamDir answered){
SalStreamDir res=local;
if (local==SalStreamSendRecv){
if (answered==SalStreamRecvOnly){
@ -124,6 +124,30 @@ static SalStreamDir compute_dir(SalStreamDir local, SalStreamDir answered){
return res;
}
static SalStreamDir compute_dir_incoming(SalStreamDir local, SalStreamDir offered){
SalStreamDir res=SalStreamSendRecv;
if (local==SalStreamSendRecv){
if (offered==SalStreamSendOnly)
res=SalStreamRecvOnly;
else if (offered==SalStreamRecvOnly)
res=SalStreamSendOnly;
else if (offered==SalStreamInactive)
res=SalStreamInactive;
else
res=SalStreamSendRecv;
}else if (local==SalStreamSendOnly){
if (offered==SalStreamRecvOnly || offered==SalStreamSendRecv)
res=SalStreamSendOnly;
else res=SalStreamInactive;
}else if (local==SalStreamRecvOnly){
if (offered==SalStreamSendOnly || offered==SalStreamSendRecv)
res=SalStreamRecvOnly;
else
res=SalStreamInactive;
}else res=SalStreamInactive;
return res;
}
static void initiate_outgoing(const SalStreamDescription *local_offer,
const SalStreamDescription *remote_answer,
SalStreamDescription *result){
@ -131,7 +155,7 @@ static void initiate_outgoing(const SalStreamDescription *local_offer,
result->payloads=match_payloads(local_offer->payloads,remote_answer->payloads,TRUE,FALSE);
result->proto=local_offer->proto;
result->type=local_offer->type;
result->dir=compute_dir(local_offer->dir,remote_answer->dir);
result->dir=compute_dir_outgoing(local_offer->dir,remote_answer->dir);
if (result->payloads && !only_telephone_event(result->payloads)){
strcpy(result->addr,remote_answer->addr);
@ -150,18 +174,12 @@ static void initiate_incoming(const SalStreamDescription *local_cap,
result->payloads=match_payloads(local_cap->payloads,remote_offer->payloads, FALSE, one_matching_codec);
result->proto=local_cap->proto;
result->type=local_cap->type;
if (remote_offer->dir==SalStreamSendOnly)
result->dir=SalStreamRecvOnly;
else if (remote_offer->dir==SalStreamRecvOnly){
result->dir=SalStreamSendOnly;
}else if (remote_offer->dir==SalStreamInactive){
result->dir=SalStreamInactive;
}else result->dir=SalStreamSendRecv;
result->dir=compute_dir_incoming(local_cap->dir,remote_offer->dir);
if (result->payloads && !only_telephone_event(result->payloads)){
strcpy(result->addr,local_cap->addr);
result->port=local_cap->port;
result->bandwidth=local_cap->bandwidth;
result->ptime=local_cap->ptime;
result->ptime=local_cap->ptime;
}else{
result->port=0;
}
@ -187,6 +205,7 @@ int offer_answer_initiate_outgoing(const SalMediaDescription *local_offer,
else ms_warning("No matching stream for %i",i);
}
result->nstreams=j;
result->bandwidth=remote_answer->bandwidth;
strcpy(result->addr,remote_answer->addr);
return 0;
}
@ -199,21 +218,30 @@ int offer_answer_initiate_outgoing(const SalMediaDescription *local_offer,
int offer_answer_initiate_incoming(const SalMediaDescription *local_capabilities,
const SalMediaDescription *remote_offer,
SalMediaDescription *result, bool_t one_matching_codec){
int i,j;
int i;
const SalStreamDescription *ls,*rs;
for(i=0,j=0;i<remote_offer->nstreams;++i){
for(i=0;i<remote_offer->nstreams;++i){
rs=&remote_offer->streams[i];
ms_message("Processing for stream %i",i);
ls=sal_media_description_find_stream((SalMediaDescription*)local_capabilities,rs->proto,rs->type);
if (ls){
initiate_incoming(ls,rs,&result->streams[j],one_matching_codec);
++j;
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 */
result->streams[i].dir=SalStreamInactive;
result->streams[i].port=0;
result->streams[i].type=rs->type;
if (rs->type==SalOther){
strncpy(result->streams[i].typeother,rs->typeother,sizeof(rs->typeother)-1);
}
}
}
result->nstreams=j;
result->nstreams=i;
strcpy(result->username, local_capabilities->username);
strcpy(result->addr,local_capabilities->addr);
result->bandwidth=local_capabilities->bandwidth;
result->session_ver=local_capabilities->session_ver;
result->session_id=local_capabilities->session_id;
return 0;
}

View file

@ -26,6 +26,7 @@
#define _PRIVATE_H
#include "linphonecore.h"
#include "linphonecore_utils.h"
#include "sal.h"
#ifdef HAVE_CONFIG_H
@ -88,13 +89,16 @@ struct _LinphoneCall
struct _VideoStream *videostream;
char *refer_to;
LinphoneCallParams params;
LinphoneCallParams current_params;
int up_bw; /*upload bandwidth setting at the time the call is started. Used to detect if it changes during a call */
int audio_bw; /*upload bandwidth used by audio */
bool_t refer_pending;
bool_t media_pending;
bool_t audio_muted;
bool_t camera_active;
bool_t all_muted; /*this flag is set during early medias*/
bool_t playing_ringbacktone;
bool_t owns_call_log;
};
@ -146,6 +150,11 @@ static inline bool_t bandwidth_is_greater(int bw1, int bw2){
else return bw1>=bw2;
}
static inline int get_video_bandwidth(int total, int audio){
if (total<=0) return 0;
return total-audio-10;
}
static inline void set_string(char **dest, const char *src){
if (*dest){
ms_free(*dest);
@ -170,7 +179,7 @@ void linphone_subscription_closed(LinphoneCore *lc, SalOp *op);
MSList *linphone_find_friend(MSList *fl, const LinphoneAddress *fri, LinphoneFriend **lf);
void linphone_core_update_allocated_audio_bandwidth(LinphoneCore *lc);
void linphone_core_update_allocated_audio_bandwidth_in_call(LinphoneCore *lc, const PayloadType *pt);
void linphone_core_update_allocated_audio_bandwidth_in_call(LinphoneCall *call, const PayloadType *pt);
void linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call);
void linphone_core_send_initial_subscribes(LinphoneCore *lc);
@ -411,16 +420,13 @@ struct _LinphoneCore
char *play_file;
char *rec_file;
time_t prevtime;
int dw_audio_bw;
int up_audio_bw;
int dw_video_bw;
int up_video_bw;
int audio_bw;
LinphoneWaitingCallback wait_cb;
void *wait_ctx;
unsigned long video_window_id;
unsigned long preview_window_id;
time_t netup_time; /*time when network went reachable */
struct _EcCalibrator *ecc;
bool_t use_files;
bool_t apply_nat_settings;
bool_t initial_subscribes_sent;
@ -429,6 +435,7 @@ struct _LinphoneCore
bool_t auto_net_state_mon;
bool_t network_reachable;
bool_t use_preview_window;
bool_t ringstream_autorelease;
};
bool_t linphone_core_can_we_add_call(LinphoneCore *lc);
@ -440,6 +447,7 @@ int linphone_core_get_calls_nb(const LinphoneCore *lc);
void linphone_core_set_state(LinphoneCore *lc, LinphoneGlobalState gstate, const char *message);
SalMediaDescription *create_local_media_description(LinphoneCore *lc, LinphoneCall *call);
void update_local_media_description(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription **md);
void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *new_md);
@ -448,6 +456,27 @@ bool_t linphone_core_is_payload_type_usable_for_bandwidth(LinphoneCore *lc, Payl
#define linphone_core_ready(lc) ((lc)->state!=LinphoneGlobalStartup)
void _linphone_core_configure_resolver();
struct _EcCalibrator{
ms_thread_t thread;
MSSndCard *play_card,*capt_card;
MSFilter *sndread,*det,*rec;
MSFilter *play, *gen, *sndwrite,*resampler;
MSTicker *ticker;
LinphoneEcCalibrationCallback cb;
void *cb_data;
int recv_count;
int sent_count;
int64_t acc;
int delay;
LinphoneEcCalibratorStatus status;
};
typedef struct _EcCalibrator EcCalibrator;
LinphoneEcCalibratorStatus ec_calibrator_get_status(EcCalibrator *ecc);
void ec_calibrator_destroy(EcCalibrator *ecc);
#define HOLD_OFF (0)
#define HOLD_ON (1)

View file

@ -215,7 +215,6 @@ void linphone_proxy_config_expires(LinphoneProxyConfig *obj, int val){
void linphone_proxy_config_enable_publish(LinphoneProxyConfig *obj, bool_t val){
obj->publish=val;
}
/**
* Starts editing a proxy configuration.
*

View file

@ -79,19 +79,41 @@ void sal_media_description_set_dir(SalMediaDescription *md, SalStreamDir stream_
}
}
bool_t sal_media_description_has_dir(const SalMediaDescription *md, SalStreamDir stream_dir){
static bool_t is_null_address(const char *addr){
return strcmp(addr,"0.0.0.0")==0 || strcmp(addr,"::0")==0;
}
/*check for the presence of at least one stream with requested direction */
static bool_t has_dir(const SalMediaDescription *md, SalStreamDir stream_dir){
int i;
bool_t found=FALSE;
/* we are looking for at least one stream with requested direction, inactive streams are ignored*/
for(i=0;i<md->nstreams;++i){
const SalStreamDescription *ss=&md->streams[i];
if (ss->dir==stream_dir) found=TRUE;
else{
if (ss->dir!=SalStreamInactive) return FALSE;
}
if (ss->dir==stream_dir) return TRUE;
if (stream_dir==SalStreamSendOnly && (is_null_address(md->addr) || is_null_address(ss->addr)))
return TRUE;
}
return found;
return FALSE;
}
bool_t sal_media_description_has_dir(const SalMediaDescription *md, SalStreamDir stream_dir){
if (stream_dir==SalStreamRecvOnly){
if (has_dir(md,SalStreamSendOnly) || has_dir(md,SalStreamSendRecv)) return FALSE;
else return TRUE;
}else if (stream_dir==SalStreamSendOnly){
if (has_dir(md,SalStreamRecvOnly) || has_dir(md,SalStreamSendRecv)) return FALSE;
else return TRUE;
}else if (stream_dir==SalStreamSendRecv){
return has_dir(md,SalStreamSendRecv);
}else{
/*SalStreamInactive*/
if (has_dir(md,SalStreamSendOnly) || has_dir(md,SalStreamSendRecv) || has_dir(md,SalStreamRecvOnly))
return FALSE;
else return TRUE;
}
return FALSE;
}
/*
@ -128,7 +150,6 @@ static bool_t payload_list_equals(const MSList *l1, const MSList *l2){
}
if (e1!=NULL || e2!=NULL){
/*means one list is longer than the other*/
abort();
return FALSE;
}
return TRUE;
@ -267,3 +288,24 @@ void __sal_op_free(SalOp *op){
sal_media_description_unref(b->remote_media);
ms_free(op);
}
SalAuthInfo* sal_auth_info_new() {
return ms_new0(SalAuthInfo,1);
}
SalAuthInfo* sal_auth_info_clone(const SalAuthInfo* auth_info) {
SalAuthInfo* new_auth_info=sal_auth_info_new();
new_auth_info->username=auth_info->username?ms_strdup(auth_info->username):NULL;
new_auth_info->userid=auth_info->userid?ms_strdup(auth_info->userid):NULL;
new_auth_info->realm=auth_info->realm?ms_strdup(auth_info->realm):NULL;
new_auth_info->password=auth_info->password?ms_strdup(auth_info->password):NULL;
return new_auth_info;
}
void sal_auth_info_delete(const SalAuthInfo* auth_info) {
if (auth_info->username) ms_free(auth_info->username);
if (auth_info->userid) ms_free(auth_info->userid);
if (auth_info->realm) ms_free(auth_info->realm);
if (auth_info->password) ms_free(auth_info->password);
ms_free((void*)auth_info);
}

View file

@ -103,6 +103,7 @@ typedef struct SalEndpointCandidate{
typedef struct SalStreamDescription{
SalMediaProto proto;
SalStreamType type;
char typeother[32];
char addr[64];
int port;
MSList *payloads; //<list of PayloadType
@ -120,6 +121,8 @@ typedef struct SalMediaDescription{
char username[64];
int nstreams;
int bandwidth;
unsigned int session_ver;
unsigned int session_id;
SalStreamDescription streams[SAL_MEDIA_DESCRIPTION_MAX_STREAMS];
} SalMediaDescription;
@ -192,6 +195,7 @@ typedef void (*SalOnCallAck)(SalOp *op);
typedef void (*SalOnCallUpdating)(SalOp *op);/*< Called when a reINVITE is received*/
typedef void (*SalOnCallTerminated)(SalOp *op, const char *from);
typedef void (*SalOnCallFailure)(SalOp *op, SalError error, SalReason reason, const char *details, int code);
typedef void (*SalOnCallReleased)(SalOp *salop);
typedef void (*SalOnAuthRequested)(SalOp *op, const char *realm, const char *username);
typedef void (*SalOnAuthSuccess)(SalOp *op, const char *realm, const char *username);
typedef void (*SalOnRegisterSuccess)(SalOp *op, bool_t registered);
@ -215,6 +219,7 @@ typedef struct SalCallbacks{
SalOnCallUpdating call_updating;
SalOnCallTerminated call_terminated;
SalOnCallFailure call_failure;
SalOnCallReleased call_released;
SalOnAuthRequested auth_requested;
SalOnAuthSuccess auth_success;
SalOnRegisterSuccess register_success;
@ -238,6 +243,10 @@ typedef struct SalAuthInfo{
char *realm;
}SalAuthInfo;
SalAuthInfo* sal_auth_info_new();
SalAuthInfo* sal_auth_info_clone(const SalAuthInfo* auth_info);
void sal_auth_info_delete(const SalAuthInfo* auth_info);
void sal_set_callbacks(Sal *ctx, const SalCallbacks *cbs);
int sal_listen_port(Sal *ctx, const char *addr, int port, SalTransport tr, int is_secure);
int sal_unlisten_ports(Sal *ctx);
@ -245,7 +254,13 @@ 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);
/**
* returns keepalive period in ms
* 0 desactiaved
* */
unsigned int sal_get_keepalive_period(Sal *ctx);
void sal_use_session_timers(Sal *ctx, int expires);
void sal_use_double_registrations(Sal *ctx, bool_t enabled);
void sal_use_one_matching_codec_policy(Sal *ctx, bool_t one_matching_codec);
int sal_iterate(Sal *sal);
MSList * sal_get_pending_auths(Sal *sal);
@ -261,6 +276,7 @@ void sal_op_set_from(SalOp *op, const char *from);
void sal_op_set_to(SalOp *op, const char *to);
void sal_op_release(SalOp *h);
void sal_op_authenticate(SalOp *h, const SalAuthInfo *info);
void sal_op_cancel_authentication(SalOp *h);
void sal_op_set_user_pointer(SalOp *h, void *up);
int sal_op_get_auth_requested(SalOp *h, const char **realm, const char **username);
const char *sal_op_get_from(const SalOp *op);
@ -281,8 +297,7 @@ int sal_call_notify_ringing(SalOp *h, bool_t early_media);
/*accept an incoming call or, during a call accept a reINVITE*/
int sal_call_accept(SalOp*h);
int sal_call_decline(SalOp *h, SalReason reason, const char *redirection /*optional*/);
int sal_call_hold(SalOp *h, bool_t holdon);
int sal_call_update(SalOp *h);
int sal_call_update(SalOp *h, const char *subject);
SalMediaDescription * sal_call_get_final_media_description(SalOp *h);
int sal_call_refer(SalOp *h, const char *refer_to);
int sal_call_refer_with_replaces(SalOp *h, SalOp *other_call_h);
@ -294,6 +309,7 @@ SalOp *sal_call_get_replaces(SalOp *h);
int sal_call_send_dtmf(SalOp *h, char dtmf);
int sal_call_terminate(SalOp *h);
bool_t sal_call_autoanswer_asked(SalOp *op);
void sal_call_send_vfu_request(SalOp *h);
/*Registration*/
int sal_register(SalOp *op, const char *proxy, const char *from, int expires);

View file

@ -21,7 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#endif
#include "sal_eXosip2.h"
#include "private.h"
#include "offeranswer.h"
static void text_received(Sal *sal, eXosip_event_t *ev);
@ -165,6 +165,7 @@ SalOp * sal_op_new(Sal *sal){
op->referred_by=NULL;
op->masquerade_via=FALSE;
op->auto_answer_asked=FALSE;
op->auth_info=NULL;
return op;
}
@ -209,6 +210,9 @@ void sal_op_release(SalOp *op){
if (op->referred_by){
ms_free(op->referred_by);
}
if (op->auth_info) {
sal_auth_info_delete(op->auth_info);
}
__sal_op_free(op);
}
@ -260,6 +264,7 @@ Sal * sal_init(){
eXosip_init();
sal=ms_new0(Sal,1);
sal->keepalive_period=30;
sal->double_reg=TRUE;
return sal;
}
@ -292,6 +297,8 @@ void sal_set_callbacks(Sal *ctx, const SalCallbacks *cbs){
ctx->callbacks.call_failure=(SalOnCallFailure)unimplemented_stub;
if (ctx->callbacks.call_terminated==NULL)
ctx->callbacks.call_terminated=(SalOnCallTerminated)unimplemented_stub;
if (ctx->callbacks.call_released==NULL)
ctx->callbacks.call_released=(SalOnCallReleased)unimplemented_stub;
if (ctx->callbacks.call_updating==NULL)
ctx->callbacks.call_updating=(SalOnCallUpdating)unimplemented_stub;
if (ctx->callbacks.auth_requested==NULL)
@ -330,13 +337,17 @@ int sal_listen_port(Sal *ctx, const char *addr, int port, SalTransport tr, int i
int err;
bool_t ipv6;
int proto=IPPROTO_UDP;
int keepalive = ctx->keepalive_period;
switch (tr) {
case SalTransportDatagram:
proto=IPPROTO_UDP;
eXosip_set_option (EXOSIP_OPT_UDP_KEEP_ALIVE, &keepalive);
break;
case SalTransportStream:
proto= IPPROTO_TCP;
keepalive=-1;
eXosip_set_option (EXOSIP_OPT_UDP_KEEP_ALIVE,&keepalive);
break;
default:
ms_warning("unexpected proto, using datagram");
@ -357,7 +368,7 @@ int sal_listen_port(Sal *ctx, const char *addr, int port, SalTransport tr, int i
#ifdef HAVE_EXOSIP_GET_SOCKET
ms_message("Exosip has socket number %i",eXosip_get_socket(proto));
#endif
eXosip_set_option (EXOSIP_OPT_UDP_KEEP_ALIVE, &ctx->keepalive_period);
ctx->running=TRUE;
return err;
}
@ -387,6 +398,10 @@ MSList *sal_get_pending_auths(Sal *sal){
return ms_list_copy(sal->pending_auths);
}
void sal_use_double_registrations(Sal *ctx, bool_t enabled){
ctx->double_reg=enabled;
}
static int extract_received_rport(osip_message_t *msg, const char **received, int *rportval){
osip_via_t *via=NULL;
osip_generic_param_t *param=NULL;
@ -455,6 +470,8 @@ static void sdp_process(SalOp *h){
int i;
offer_answer_initiate_incoming(h->base.local_media,h->base.remote_media,h->result,h->base.root->one_matching_codec);
h->sdp_answer=media_description_to_sdp(h->result);
/*once we have generated the SDP answer, we modify the result description for processing by the upper layer.
It should contains media parameters constraint from the remote offer, not our response*/
strcpy(h->result->addr,h->base.remote_media->addr);
h->result->bandwidth=h->base.remote_media->bandwidth;
for(i=0;i<h->result->nstreams;++i){
@ -637,6 +654,7 @@ int sal_ping(SalOp *op, const char *from, const char *to){
sal_op_set_from(op,from);
sal_op_set_to(op,to);
/*bug here: eXosip2 does not honor the route argument*/
eXosip_options_build_request (&options, sal_op_get_to(op),
sal_op_get_from(op),sal_op_get_route(op));
if (options){
@ -732,38 +750,59 @@ int sal_call_send_dtmf(SalOp *h, char dtmf){
return 0;
}
static void push_auth_to_exosip(const SalAuthInfo *info){
const char *userid;
if (info->userid==NULL || info->userid[0]=='\0') userid=info->username;
else userid=info->userid;
ms_message("Authentication info for username [%s], id[%s], realm [%s] added to eXosip", info->username,userid, info->realm);
eXosip_add_authentication_info (info->username,userid,
info->password, NULL,info->realm);
}
/*
* Just for symmetry ;-)
*/
static void pop_auth_from_exosip() {
eXosip_clear_authentication_info();
}
int sal_call_terminate(SalOp *h){
int err;
if (h->auth_info) push_auth_to_exosip(h->auth_info);
eXosip_lock();
err=eXosip_call_terminate(h->cid,h->did);
eXosip_unlock();
pop_auth_from_exosip();
if (err!=0){
ms_warning("Exosip could not terminate the call: cid=%i did=%i", h->cid,h->did);
}
sal_remove_call(h->base.root,h);
h->cid=-1;
return 0;
}
void sal_op_authenticate(SalOp *h, const SalAuthInfo *info){
if (h->pending_auth){
const char *userid;
if (info->userid==NULL || info->userid[0]=='\0') userid=info->username;
else userid=info->userid;
ms_message("Authentication info for %s %s added to eXosip", info->username,info->realm);
eXosip_add_authentication_info (info->username,userid,
info->password, NULL,info->realm);
push_auth_to_exosip(info);
eXosip_lock();
eXosip_default_action(h->pending_auth);
eXosip_unlock();
ms_message("eXosip_default_action() done");
eXosip_clear_authentication_info();
pop_auth_from_exosip();
eXosip_event_free(h->pending_auth);
sal_remove_pending_auth(sal_op_get_sal(h),h);
h->pending_auth=NULL;
if (h->auth_info) sal_auth_info_delete(h->auth_info); /*if already exist*/
h->auth_info=sal_auth_info_clone(info); /*store auth info for subsequent request*/
}
}
void sal_op_cancel_authentication(SalOp *h) {
if (h->rid >0) {
sal_op_get_sal(h)->callbacks.register_failure(h,SalErrorFailure, SalReasonForbidden,_("Authentication failure"));
} else if (h->cid >0) {
sal_op_get_sal(h)->callbacks.call_failure(h,SalErrorFailure, SalReasonForbidden,_("Authentication failure"),0);
} else {
ms_warning("Auth failure not handled");
}
}
static void set_network_origin(SalOp *op, osip_message_t *req){
const char *received=NULL;
int rport=5060;
@ -815,6 +854,9 @@ static SalOp *find_op(Sal *sal, eXosip_event_t *ev){
if (ev->sid>0){
return sal_find_out_subscribe(sal,ev->sid);
}
if (ev->nid>0){
return sal_find_in_subscribe(sal,ev->nid);
}
if (ev->response) return sal_find_other(sal,ev->response);
return NULL;
}
@ -1033,8 +1075,6 @@ static void call_terminated(Sal *sal, eXosip_event_t *ev){
if (ev->request){
osip_from_to_str(ev->request->from,&from);
}
sal_remove_call(sal,op);
op->cid=-1;
sal->callbacks.call_terminated(op,from!=NULL ? from : sal_op_get_from(op));
if (from) osip_free(from);
}
@ -1045,9 +1085,10 @@ static void call_released(Sal *sal, eXosip_event_t *ev){
ms_warning("No op associated to this call_released()");
return;
}
op->cid=-1;
if (op->did==-1)
if (op->did==-1) {
sal->callbacks.call_failure(op,SalErrorNoResponse,SalReasonUnknown,NULL, 487);
}
sal->callbacks.call_released(op);
}
static int get_auth_data_from_response(osip_message_t *resp, const char **realm, const char **username){
@ -1216,6 +1257,33 @@ static bool_t call_failure(Sal *sal, eXosip_event_t *ev){
return TRUE;
}
/* Request remote side to send us VFU */
void sal_call_send_vfu_request(SalOp *h){
osip_message_t *msg=NULL;
char info_body[] =
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>"
"<media_control>"
" <vc_primitive>"
" <to_encoder>"
" <picture_fast_update></picture_fast_update>"
" </to_encoder>"
" </vc_primitive>"
"</media_control>";
char clen[10];
eXosip_lock();
eXosip_call_build_info(h->did,&msg);
if (msg){
osip_message_set_body(msg,info_body,strlen(info_body));
osip_message_set_content_type(msg,"application/media_control+xml");
snprintf(clen,sizeof(clen),"%lu",(unsigned long)strlen(info_body));
osip_message_set_content_length(msg,clen);
eXosip_call_send_request(h->did,msg);
ms_message("Sending VFU request !");
}
eXosip_unlock();
}
static void process_media_control_xml(Sal *sal, eXosip_event_t *ev){
SalOp *op=find_op(sal,ev);
@ -1505,6 +1573,9 @@ static bool_t register_again_with_updated_contact(SalOp *op, osip_message_t *ori
char *tmp;
char port[20];
SalAddress *addr;
Sal *sal=op->base.root;
if (sal->double_reg==FALSE) return FALSE;
if (extract_received_rport(last_answer,&received,&rport)==-1) return FALSE;
osip_message_get_contact(orig_request,0,&ctt);
@ -1681,7 +1752,7 @@ static bool_t process_event(Sal *sal, eXosip_event_t *ev){
call_message_new(sal,ev);
break;
case EXOSIP_CALL_MESSAGE_REQUESTFAILURE:
if (ev->did<0 && ev->response &&
if (ev->response &&
(ev->response->status_code==407 || ev->response->status_code==401)){
return process_authentication(sal,ev);
}
@ -1736,6 +1807,7 @@ static bool_t process_event(Sal *sal, eXosip_event_t *ev){
other_request_reply(sal,ev);
break;
case EXOSIP_MESSAGE_REQUESTFAILURE:
case EXOSIP_NOTIFICATION_REQUESTFAILURE:
if (ev->response) {
switch (ev->response->status_code) {
case 407:
@ -1934,6 +2006,9 @@ void sal_set_keepalive_period(Sal *ctx,unsigned int value) {
ctx->keepalive_period=value;
eXosip_set_option (EXOSIP_OPT_UDP_KEEP_ALIVE, &value);
}
unsigned int sal_get_keepalive_period(Sal *ctx) {
return ctx->keepalive_period;
}
const char * sal_address_get_port(const SalAddress *addr) {
const osip_from_t *u=(const osip_from_t*)addr;
@ -1949,47 +2024,18 @@ int sal_address_get_port_int(const SalAddress *uri) {
}
}
/*
* Send a re-Invite used to hold the current call
*/
int sal_call_hold(SalOp *h, bool_t holdon)
{
int err=0;
osip_message_t *reinvite=NULL;
if(eXosip_call_build_request(h->did,"INVITE",&reinvite) != OSIP_SUCCESS || reinvite==NULL)
return -1;
osip_message_set_subject(reinvite,holdon ? "Phone call hold" : "Phone call resume" );
osip_message_set_allow(reinvite, "INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO");
if (h->base.root->session_expires!=0){
osip_message_set_header(reinvite, "Session-expires", "200");
osip_message_set_supported(reinvite, "timer");
}
//add something to say that the distant sip phone will be in sendonly/sendrecv mode
if (h->base.local_media){
h->sdp_offering=TRUE;
sal_media_description_set_dir(h->base.local_media, holdon ? SalStreamSendOnly : SalStreamSendRecv);
set_sdp_from_desc(reinvite,h->base.local_media);
}else h->sdp_offering=FALSE;
eXosip_lock();
err = eXosip_call_send_request(h->did, reinvite);
eXosip_unlock();
return err;
}
/* sends a reinvite. Local media description may have changed by application since call establishment*/
int sal_call_update(SalOp *h){
int sal_call_update(SalOp *h, const char *subject){
int err=0;
osip_message_t *reinvite=NULL;
eXosip_lock();
if(eXosip_call_build_request(h->did,"INVITE",&reinvite) != OSIP_SUCCESS || reinvite==NULL){
if(eXosip_call_build_request(h->did,"INVITE",&reinvite) != 0 || reinvite==NULL){
eXosip_unlock();
return -1;
}
eXosip_unlock();
osip_message_set_subject(reinvite,osip_strdup("Phone call parameters updated"));
osip_message_set_subject(reinvite,subject);
osip_message_set_allow(reinvite, "INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO");
if (h->base.root->session_expires!=0){
osip_message_set_header(reinvite, "Session-expires", "200");

View file

@ -41,6 +41,7 @@ struct Sal{
int keepalive_period;
void *up;
bool_t one_matching_codec;
bool_t double_reg;
};
struct SalOp{
@ -64,6 +65,7 @@ struct SalOp{
bool_t reinvite;
bool_t masquerade_via;
bool_t auto_answer_asked;
const SalAuthInfo *auth_info;
};
void sal_remove_out_subscribe(Sal *sal, SalOp *op);
@ -77,6 +79,7 @@ void sal_exosip_subscription_closed(Sal *sal,eXosip_event_t *ev);
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 _osip_list_set_empty(osip_list_t *l, void (*freefunc)(void*));

View file

@ -39,6 +39,7 @@ SalOp * sal_find_out_subscribe(Sal *sal, int sid){
op=(SalOp*)elem->data;
if (op->sid==sid) return op;
}
ms_message("No op for sid %i",sid);
return NULL;
}
@ -50,7 +51,7 @@ void sal_remove_out_subscribe(Sal *sal, SalOp *op){
sal->out_subscribes=ms_list_remove(sal->out_subscribes,op);
}
static SalOp * sal_find_in_subscribe(Sal *sal, int nid){
SalOp * sal_find_in_subscribe(Sal *sal, int nid){
const MSList *elem;
SalOp *op;
for(elem=sal->in_subscribes;elem!=NULL;elem=elem->next){
@ -569,6 +570,7 @@ int sal_notify_presence(SalOp *op, SalPresenceStatus status, const char *status_
if (msg!=NULL){
const char *identity=sal_op_get_contact(op);
if (identity==NULL) identity=sal_op_get_to(op);
_osip_list_set_empty(&msg->contacts,(void (*)(void*))osip_contact_free);
osip_message_set_contact(msg,identity);
add_presence_body(msg,status);
eXosip_insubscription_send_request(op->did,msg);

View file

@ -127,14 +127,18 @@ static sdp_message_t *create_generic_sdp(const SalMediaDescription *desc)
{
sdp_message_t *local;
int inet6;
char sessid[16];
char sessver[16];
snprintf(sessid,16,"%i",desc->session_id);
snprintf(sessver,16,"%i",desc->session_ver);
sdp_message_init (&local);
if (strchr(desc->addr,':')!=NULL){
inet6=1;
}else inet6=0;
sdp_message_v_version_set (local, osip_strdup ("0"));
sdp_message_o_origin_set (local, osip_strdup (desc->username),
osip_strdup ("123456"), osip_strdup ("654321"),
osip_strdup (sessid), osip_strdup (sessver),
osip_strdup ("IN"), inet6 ? osip_strdup("IP6") : osip_strdup ("IP4"),
osip_strdup (desc->addr));
sdp_message_s_name_set (local, osip_strdup ("A conversation"));
@ -181,11 +185,23 @@ static void add_payload(sdp_message_t *msg, int line, const PayloadType *pt)
static void add_line(sdp_message_t *msg, int lineno, const SalStreamDescription *desc){
const char *mt=desc->type==SalAudio ? "audio" : "video";
const char *mt=NULL;
const MSList *elem;
const char *addr;
const char *dir="sendrecv";
int port;
switch (desc->type) {
case SalAudio:
mt="audio";
break;
case SalVideo:
mt="video";
break;
case SalOther:
mt=desc->typeother;
break;
}
if (desc->candidates[0].addr[0]!='\0'){
addr=desc->candidates[0].addr;
port=desc->candidates[0].port;
@ -310,7 +326,10 @@ int sdp_to_media_description(sdp_message_t *msg, SalMediaDescription *desc){
stream->type=SalAudio;
}else if (strcasecmp("video", mtype) == 0){
stream->type=SalVideo;
}else stream->type=SalOther;
}else {
stream->type=SalOther;
strncpy(stream->typeother,mtype,sizeof(stream->typeother)-1);
}
for(j=0;(sbw=sdp_message_bandwidth_get(msg,i,j))!=NULL;++j){
if (strcasecmp(sbw->b_bwtype,"AS")==0) stream->bandwidth=atoi(sbw->b_bandwidth);
}

46
coreapi/test_ecc.c Normal file
View file

@ -0,0 +1,46 @@
/*
linphone
Copyright (C) 2011 Belledonne Communications SARL
Author: Simon MORLAT (simon.morlat@linphone.org)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "linphonecore.h"
#include "linphonecore_utils.h"
static void calibration_finished(LinphoneCore *lc, LinphoneEcCalibratorStatus status, int delay, void *data){
ms_message("echo calibration finished %s.",status==LinphoneEcCalibratorDone ? "successfully" : "with faillure");
if (status==LinphoneEcCalibratorDone) ms_message("Measured delay is %i",delay);
}
int main(int argc, char *argv[]){
int count=0;
LinphoneCoreVTable vtable={0};
LinphoneCore *lc=linphone_core_new(&vtable,NULL,NULL,NULL);
linphone_core_enable_logs(NULL);
linphone_core_start_echo_calibration(lc,calibration_finished,NULL);
while(count++<1000){
linphone_core_iterate(lc);
ms_usleep(10000);
}
linphone_core_destroy(lc);
return 0;
}

View file

@ -4,7 +4,6 @@
# It must be run within a gtk+ binary bundle tree, such as in the zip bundle
# downloadable from www.gtk.org
echo bin
echo bin/libglade-2.0-0.dll
find bin -name *.dll
find lib/gtk-2.0
find etc

152
gtk+-2.22.1.filelist Normal file
View file

@ -0,0 +1,152 @@
bin
bin/freetype6.dll
bin/intl.dll
bin/libasprintf-0.dll
bin/libatk-1.0-0.dll
bin/libcairo-2.dll
bin/libcairo-gobject-2.dll
bin/libcairo-script-interpreter-2.dll
bin/libexpat-1.dll
bin/libfontconfig-1.dll
bin/libgailutil-18.dll
bin/libgcc_s_dw2-1.dll
bin/libgdk-win32-2.0-0.dll
bin/libgdk_pixbuf-2.0-0.dll
bin/libgio-2.0-0.dll
bin/libglib-2.0-0.dll
bin/libgmodule-2.0-0.dll
bin/libgobject-2.0-0.dll
bin/libgthread-2.0-0.dll
bin/libgtk-win32-2.0-0.dll
bin/libpango-1.0-0.dll
bin/libpangocairo-1.0-0.dll
bin/libpangoft2-1.0-0.dll
bin/libpangowin32-1.0-0.dll
bin/libpng14-14.dll
bin/zlib1.dll
lib/gtk-2.0
lib/gtk-2.0/2.10.0
lib/gtk-2.0/2.10.0/engines
lib/gtk-2.0/2.10.0/engines/libpixmap.dll
lib/gtk-2.0/2.10.0/engines/libwimp.dll
lib/gtk-2.0/include
lib/gtk-2.0/include/gdkconfig.h
lib/gtk-2.0/modules
lib/gtk-2.0/modules/libgail.dll
etc
etc/fonts
etc/fonts/fonts.conf
etc/fonts/fonts.dtd
etc/gtk-2.0
etc/gtk-2.0/gtk.immodules
etc/gtk-2.0/im-multipress.conf
etc/pango
etc/pango/pango.modules
share/locale/fr
share/locale/fr/LC_MESSAGES
share/locale/fr/LC_MESSAGES/atk10.mo
share/locale/fr/LC_MESSAGES/gdk-pixbuf.mo
share/locale/fr/LC_MESSAGES/gettext-runtime.mo
share/locale/fr/LC_MESSAGES/glib20.mo
share/locale/fr/LC_MESSAGES/gtk20-properties.mo
share/locale/fr/LC_MESSAGES/gtk20.mo
share/locale/de
share/locale/de/LC_MESSAGES
share/locale/de/LC_MESSAGES/atk10.mo
share/locale/de/LC_MESSAGES/gdk-pixbuf.mo
share/locale/de/LC_MESSAGES/gettext-runtime.mo
share/locale/de/LC_MESSAGES/glib20.mo
share/locale/de/LC_MESSAGES/gtk20-properties.mo
share/locale/de/LC_MESSAGES/gtk20.mo
share/locale/sv
share/locale/sv/LC_MESSAGES
share/locale/sv/LC_MESSAGES/atk10.mo
share/locale/sv/LC_MESSAGES/gdk-pixbuf.mo
share/locale/sv/LC_MESSAGES/gettext-runtime.mo
share/locale/sv/LC_MESSAGES/glib20.mo
share/locale/sv/LC_MESSAGES/gtk20-properties.mo
share/locale/sv/LC_MESSAGES/gtk20.mo
share/locale/cs
share/locale/cs/LC_MESSAGES
share/locale/cs/LC_MESSAGES/atk10.mo
share/locale/cs/LC_MESSAGES/gdk-pixbuf.mo
share/locale/cs/LC_MESSAGES/gettext-runtime.mo
share/locale/cs/LC_MESSAGES/glib20.mo
share/locale/cs/LC_MESSAGES/gtk20-properties.mo
share/locale/cs/LC_MESSAGES/gtk20.mo
share/locale/es
share/locale/es/LC_MESSAGES
share/locale/es/LC_MESSAGES/atk10.mo
share/locale/es/LC_MESSAGES/gdk-pixbuf.mo
share/locale/es/LC_MESSAGES/gettext-runtime.mo
share/locale/es/LC_MESSAGES/glib20.mo
share/locale/es/LC_MESSAGES/gtk20-properties.mo
share/locale/es/LC_MESSAGES/gtk20.mo
share/locale/hu
share/locale/hu/LC_MESSAGES
share/locale/hu/LC_MESSAGES/atk10.mo
share/locale/hu/LC_MESSAGES/gdk-pixbuf.mo
share/locale/hu/LC_MESSAGES/glib20.mo
share/locale/hu/LC_MESSAGES/gtk20-properties.mo
share/locale/hu/LC_MESSAGES/gtk20.mo
share/locale/it
share/locale/it/LC_MESSAGES
share/locale/it/LC_MESSAGES/atk10.mo
share/locale/it/LC_MESSAGES/gdk-pixbuf.mo
share/locale/it/LC_MESSAGES/gettext-runtime.mo
share/locale/it/LC_MESSAGES/glib20.mo
share/locale/it/LC_MESSAGES/gtk20-properties.mo
share/locale/it/LC_MESSAGES/gtk20.mo
share/locale/ja
share/locale/ja/LC_MESSAGES
share/locale/ja/LC_MESSAGES/atk10.mo
share/locale/ja/LC_MESSAGES/gdk-pixbuf.mo
share/locale/ja/LC_MESSAGES/gettext-runtime.mo
share/locale/ja/LC_MESSAGES/glib20.mo
share/locale/ja/LC_MESSAGES/gtk20-properties.mo
share/locale/ja/LC_MESSAGES/gtk20.mo
share/locale/nl
share/locale/nl/LC_MESSAGES
share/locale/nl/LC_MESSAGES/atk10.mo
share/locale/nl/LC_MESSAGES/gdk-pixbuf.mo
share/locale/nl/LC_MESSAGES/gettext-runtime.mo
share/locale/nl/LC_MESSAGES/glib20.mo
share/locale/nl/LC_MESSAGES/gtk20-properties.mo
share/locale/nl/LC_MESSAGES/gtk20.mo
share/locale/pl
share/locale/pl/LC_MESSAGES
share/locale/pl/LC_MESSAGES/atk10.mo
share/locale/pl/LC_MESSAGES/gdk-pixbuf.mo
share/locale/pl/LC_MESSAGES/gettext-runtime.mo
share/locale/pl/LC_MESSAGES/glib20.mo
share/locale/pl/LC_MESSAGES/gtk20-properties.mo
share/locale/pl/LC_MESSAGES/gtk20.mo
share/locale/ru
share/locale/ru/LC_MESSAGES
share/locale/ru/LC_MESSAGES/atk10.mo
share/locale/ru/LC_MESSAGES/gdk-pixbuf.mo
share/locale/ru/LC_MESSAGES/gettext-runtime.mo
share/locale/ru/LC_MESSAGES/glib20.mo
share/locale/ru/LC_MESSAGES/gtk20-properties.mo
share/locale/ru/LC_MESSAGES/gtk20.mo
share/locale/pt_BR
share/locale/pt_BR/LC_MESSAGES
share/locale/pt_BR/LC_MESSAGES/atk10.mo
share/locale/pt_BR/LC_MESSAGES/gdk-pixbuf.mo
share/locale/pt_BR/LC_MESSAGES/gettext-runtime.mo
share/locale/pt_BR/LC_MESSAGES/glib20.mo
share/locale/pt_BR/LC_MESSAGES/gtk20-properties.mo
share/locale/pt_BR/LC_MESSAGES/gtk20.mo
share/themes
share/themes/Default
share/themes/Default/gtk-2.0-key
share/themes/Default/gtk-2.0-key/gtkrc
share/themes/Emacs
share/themes/Emacs/gtk-2.0-key
share/themes/Emacs/gtk-2.0-key/gtkrc
share/themes/MS-Windows
share/themes/MS-Windows/gtk-2.0
share/themes/MS-Windows/gtk-2.0/gtkrc
share/themes/Raleigh
share/themes/Raleigh/gtk-2.0
share/themes/Raleigh/gtk-2.0/gtkrc

View file

@ -58,7 +58,7 @@ static GtkWidget *make_tab_header(int number){
GtkWidget *w=gtk_hbox_new (FALSE,0);
GtkWidget *i=create_pixmap ("status-green.png");
GtkWidget *l;
gchar *text=g_strdup_printf("Call %i",number);
gchar *text=g_strdup_printf("Call #%i",number);
l=gtk_label_new (text);
gtk_box_pack_start (GTK_BOX(w),i,FALSE,FALSE,0);
gtk_box_pack_end(GTK_BOX(w),l,TRUE,TRUE,0);
@ -66,6 +66,60 @@ static GtkWidget *make_tab_header(int number){
return w;
}
static void linphone_gtk_transfer_call(LinphoneCall *dest_call){
LinphoneCall *call=linphone_gtk_get_currently_displayed_call();
linphone_core_transfer_call_to_another (linphone_gtk_get_core(),call,dest_call);
}
static void transfer_button_clicked(GtkWidget *button, gpointer call_ref){
GtkWidget *menu_item;
GtkWidget *menu=gtk_menu_new();
LinphoneCall *call=(LinphoneCall*)call_ref;
LinphoneCore *lc=linphone_gtk_get_core();
const MSList *elem=linphone_core_get_calls(lc);
for(;elem!=NULL;elem=elem->next){
LinphoneCall *other_call=(LinphoneCall*)elem->data;
GtkWidget *call_view=(GtkWidget*)linphone_call_get_user_pointer(other_call);
if (other_call!=call){
int call_index=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(call_view),"call_index"));
char *remote_uri=linphone_call_get_remote_address_as_string (other_call);
char *text=g_strdup_printf("Transfer to call #%i with %s",call_index,remote_uri);
menu_item=gtk_image_menu_item_new_with_label(text);
ms_free(remote_uri);
g_free(text);
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),create_pixmap("status-green.png"));
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_transfer_call,other_call);
}
}
gtk_menu_popup(GTK_MENU(menu),NULL,NULL,NULL,NULL,0,
gtk_get_current_event_time());
gtk_widget_show(menu);
}
void linphone_gtk_enable_transfer_button(LinphoneCore *lc, gboolean value){
const MSList *elem=linphone_core_get_calls(lc);
for(;elem!=NULL;elem=elem->next){
LinphoneCall *call=(LinphoneCall*)elem->data;
GtkWidget *call_view=(GtkWidget*)linphone_call_get_user_pointer(call);
GtkWidget *box=linphone_gtk_get_widget (call_view,"mute_pause_buttons");
GtkWidget *button=(GtkWidget*)g_object_get_data(G_OBJECT(box),"transfer");
if (button && value==FALSE){
gtk_widget_destroy(button);
button=NULL;
}else if (!button && value==TRUE){
button=gtk_button_new_with_label (_("Transfer"));
gtk_button_set_image(GTK_BUTTON(button),gtk_image_new_from_stock (GTK_STOCK_GO_FORWARD,GTK_ICON_SIZE_BUTTON));
g_signal_connect(G_OBJECT(button),"clicked",(GCallback)transfer_button_clicked,call);
gtk_widget_show_all(button);
gtk_container_add(GTK_CONTAINER(box),button);
}
g_object_set_data(G_OBJECT(box),"transfer",button);
}
}
void linphone_gtk_create_in_call_view(LinphoneCall *call){
GtkWidget *call_view=linphone_gtk_create_widget("main","in_call_frame");
GtkWidget *main_window=linphone_gtk_get_main_window ();
@ -78,6 +132,8 @@ void linphone_gtk_create_in_call_view(LinphoneCall *call){
call_index=1;
}
g_object_set_data(G_OBJECT(call_view),"call",call);
g_object_set_data(G_OBJECT(call_view),"call_index",GINT_TO_POINTER(call_index));
linphone_call_set_user_pointer (call,call_view);
linphone_call_ref(call);
gtk_notebook_append_page (notebook,call_view,make_tab_header(call_index));
@ -145,6 +201,7 @@ void linphone_gtk_in_call_view_set_incoming(LinphoneCall *call, bool_t with_paus
GtkWidget *animation=linphone_gtk_get_widget(callview,"in_call_animation");
GdkPixbufAnimation *pbuf=create_pixbuf_animation("calling_anim.gif");
GtkWidget *answer_button;
GtkWidget *image;
gtk_label_set_markup(GTK_LABEL(status),_("<b>Incoming call</b>"));
gtk_widget_show_all(linphone_gtk_get_widget(callview,"answer_decline_panel"));
@ -153,14 +210,17 @@ void linphone_gtk_in_call_view_set_incoming(LinphoneCall *call, bool_t with_paus
display_peer_name_in_label(callee,linphone_call_get_remote_address (call));
answer_button=linphone_gtk_get_widget(callview,"accept_call");
gtk_button_set_image(GTK_BUTTON(answer_button),
create_pixmap (linphone_gtk_get_ui_config("start_call_icon","startcall-green.png")));
image=create_pixmap (linphone_gtk_get_ui_config("start_call_icon","startcall-green.png"));
if (with_pause){
gtk_button_set_label(GTK_BUTTON(answer_button),
_("Pause all calls\nand answer"));
}else gtk_button_set_label(GTK_BUTTON(answer_button),_("Answer"));
gtk_button_set_image(GTK_BUTTON(linphone_gtk_get_widget(callview,"decline_call")),
create_pixmap (linphone_gtk_get_ui_config("stop_call_icon","stopcall-red.png")));
gtk_button_set_image(GTK_BUTTON(answer_button),image);
gtk_widget_show(image);
image=create_pixmap (linphone_gtk_get_ui_config("stop_call_icon","stopcall-red.png"));
gtk_button_set_image(GTK_BUTTON(linphone_gtk_get_widget(callview,"decline_call")),image);
gtk_widget_show(image);
if (pbuf!=NULL){
gtk_image_set_from_animation(GTK_IMAGE(animation),pbuf);

View file

@ -1,147 +0,0 @@
<?xml version="1.0"?>
<interface>
<!-- interface-requires gtk+ 2.16 -->
<!-- interface-naming-policy toplevel-contextual -->
<object class="GtkDialog" id="incoming_call">
<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">5</property>
<property name="type">popup</property>
<property name="title" translatable="yes">Linphone - Incoming call</property>
<property name="window_position">center-on-parent</property>
<property name="icon">linphone2.png</property>
<property name="type_hint">notification</property>
<property name="urgency_hint">True</property>
<property name="deletable">False</property>
<child internal-child="vbox">
<object class="GtkVBox" id="dialog-vbox8">
<property name="visible">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="spacing">2</property>
<child>
<object class="GtkFrame" id="frame16">
<property name="visible">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="label_xalign">0</property>
<child>
<object class="GtkAlignment" id="alignment16">
<property name="visible">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="left_padding">12</property>
<child>
<object class="GtkLabel" id="message">
<property name="visible">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="label" translatable="yes">Incoming call from</property>
</object>
</child>
</object>
</child>
<child type="label">
<object class="GtkLabel" id="label43">
<property name="visible">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="label" translatable="yes">Incoming call</property>
<property name="use_markup">True</property>
</object>
</child>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
<child internal-child="action_area">
<object class="GtkHButtonBox" id="dialog-action_area7">
<property name="visible">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="layout_style">spread</property>
<child>
<object class="GtkButton" id="accept_call">
<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>
<signal handler="linphone_gtk_accept_call" name="clicked"/>
<child>
<object class="GtkHBox" id="hbox17">
<property name="visible">True</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="GtkImage" id="image12">
<property name="visible">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="stock">gtk-yes</property>
</object>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label44">
<property name="visible">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="label" translatable="yes">Accept</property>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="decline_cal">
<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>
<signal handler="linphone_gtk_decline_call" name="clicked"/>
<child>
<object class="GtkHBox" id="hbox20">
<property name="visible">True</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="GtkImage" id="image13">
<property name="visible">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="stock">gtk-no</property>
</object>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="decline_call">
<property name="visible">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="label" translatable="yes">Decline</property>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
</object>
</child>
</object>
</interface>

View file

@ -97,6 +97,7 @@ void linphone_gtk_in_call_view_set_incoming(LinphoneCall *call, bool_t with_paus
void linphone_gtk_in_call_view_set_paused(LinphoneCall *call);
void linphone_gtk_enable_mute_button(GtkButton *button, gboolean sensitive);
void linphone_gtk_enable_hold_button(LinphoneCall *call, gboolean sensitive, gboolean holdon);
void linphone_gtk_enable_transfer_button(LinphoneCore *lc, gboolean value);
void linphone_gtk_show_login_frame(LinphoneProxyConfig *cfg);
void linphone_gtk_exit_login_frame(void);

View file

@ -689,6 +689,7 @@ static void linphone_gtk_update_call_buttons(LinphoneCall *call){
bool_t start_active=TRUE;
bool_t stop_active=FALSE;
bool_t add_call=FALSE;
int call_list_size=ms_list_size(calls);
if (calls==NULL){
start_active=TRUE;
@ -699,7 +700,7 @@ static void linphone_gtk_update_call_buttons(LinphoneCall *call){
start_active=TRUE;
add_call=TRUE;
}else if (call!=NULL && linphone_call_get_state(call)==LinphoneCallIncomingReceived && all_other_calls_paused(call,calls)){
if (ms_list_size(calls)>1){
if (call_list_size>1){
start_active=TRUE;
add_call=TRUE;
}else{
@ -724,6 +725,7 @@ static void linphone_gtk_update_call_buttons(LinphoneCall *call){
GTK_BUTTON(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"main_mute")),
FALSE);
}
linphone_gtk_enable_transfer_button(lc,call_list_size>1);
update_video_title();
}
@ -1444,6 +1446,7 @@ int main(int argc, char *argv[]){
settings=gtk_settings_get_default();
g_type_class_unref (g_type_class_ref (GTK_TYPE_IMAGE_MENU_ITEM));
g_type_class_unref (g_type_class_ref (GTK_TYPE_BUTTON));
g_object_set(settings, "gtk-menu-images", TRUE, NULL);
g_object_set(settings, "gtk-button-images", TRUE, NULL);
#ifdef WIN32

View file

@ -1401,6 +1401,8 @@
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>

View file

@ -21,9 +21,10 @@ package org.linphone.core;
import java.util.Vector;
/**
* Object representing a Call. calls are created using {@link LinphoneCore#invite(LinphoneAddress)} or paased to the application by listener {@link LinphoneCoreListener#callState(LinphoneCore, LinphoneCall, State, String)}
* Object representing a Call. calls are created using {@link LinphoneCore#invite(LinphoneAddress)} or passed to the application by listener {@link LinphoneCoreListener#callState(LinphoneCore, LinphoneCall, State, String)}
*
*/
@SuppressWarnings("unchecked")
public interface LinphoneCall {
/**
* Linphone call states
@ -109,7 +110,11 @@ public interface LinphoneCall {
* The remote accepted the call update initiated by us
*/
public static final State CallUpdated = new State(17, "CallUpdated");
/**
* The call object is now released.
*/
public static final State CallReleased = new State(18,"CallReleased");
private State(int value,String stringValue) {
mValue = value;
@ -150,9 +155,32 @@ public interface LinphoneCall {
**/
public LinphoneCallLog getCallLog();
/**
* @return parameters for this call; read only, call copy() to get a read/write version.
*/
public LinphoneCallParams getCurrentParamsReadOnly();
public LinphoneCallParams getCurrentParamsCopy();
public void enableCamera(boolean enabled);
/**
* Enables or disable echo cancellation.
* @param enable
*/
public void enableEchoCancellation(boolean enable);
/**
* get EC status
* @return true if echo cancellation is enabled.
*/
public boolean isEchoCancellationEnabled();
/**
* Enables or disable echo limiter cancellation.
* @param enable
*/
public void enableEchoLimiter(boolean enable);
/**
* get EL status
* @return true if echo limiter is enabled.
*/
public boolean isEchoLimiterEnabled();
/**
* Returns the object associated to a call this one is replacing.
* Call replacement can occur during transfer scenarios.
*/
public LinphoneCall getReplacedCall();
}

View file

@ -24,7 +24,7 @@ package org.linphone.core;
import java.util.Vector;
@SuppressWarnings("unchecked")
public interface LinphoneCallLog {
/**
* Represents call status

View file

@ -28,5 +28,10 @@ package org.linphone.core;
public interface LinphoneCallParams {
void setVideoEnabled(boolean b);
boolean getVideoEnabled();
LinphoneCallParams copy();
/**
* @param value 0 to disable limitation
*/
void setAudioBandwidth(int value);
}

View file

@ -25,11 +25,12 @@ import java.util.Vector;
* Linphone core main object created by method {@link LinphoneCoreFactory#createLinphoneCore(LinphoneCoreListener, String, String, Object)}.
*
*/
@SuppressWarnings("unchecked")
public interface LinphoneCore {
/**
* linphone core states
*/
static public class GlobalState {
static public class GlobalState {
static private Vector values = new Vector();
/**
* Off
@ -72,28 +73,28 @@ public interface LinphoneCore {
* Describes proxy registration states.
*
*/
static public class RegistrationState {
static private Vector values = new Vector();
static public class RegistrationState {
private static Vector values = new Vector();
/**
* None
*/
static public RegistrationState RegistrationNone = new RegistrationState(0,"RegistrationNone");
public static RegistrationState RegistrationNone = new RegistrationState(0,"RegistrationNone");
/**
* In Progress
*/
static public RegistrationState RegistrationProgress = new RegistrationState(1,"RegistrationProgress");
public static RegistrationState RegistrationProgress = new RegistrationState(1,"RegistrationProgress");
/**
* Ok
*/
static public RegistrationState RegistrationOk = new RegistrationState(2,"RegistrationOk");
public static RegistrationState RegistrationOk = new RegistrationState(2,"RegistrationOk");
/**
* Cleared
*/
static public RegistrationState RegistrationCleared = new RegistrationState(3,"RegistrationCleared");
public static RegistrationState RegistrationCleared = new RegistrationState(3,"RegistrationCleared");
/**
* Failed
*/
static public RegistrationState RegistrationFailed = new RegistrationState(4,"RegistrationFailed");
public static RegistrationState RegistrationFailed = new RegistrationState(4,"RegistrationFailed");
private final int mValue;
private final String mStringValue;
@ -118,7 +119,7 @@ public interface LinphoneCore {
* Describes firewall policy.
*
*/
static public class FirewallPolicy {
static public class FirewallPolicy {
static private Vector values = new Vector();
/**
* No firewall is assumed.
@ -178,6 +179,50 @@ public interface LinphoneCore {
return mStringValue;
}
}
/**
* EC Calibrator Status
.
*
*/
static public class EcCalibratorStatus {
static private Vector values = new Vector();
/**
* Calibration in progress
*/
static public EcCalibratorStatus InProgress = new EcCalibratorStatus(0,"InProgress");
/**
* Calibration done
*/
static public EcCalibratorStatus Done = new EcCalibratorStatus(1,"Done");
/**
* Calibration in progress
*/
static public EcCalibratorStatus Failed = new EcCalibratorStatus(2,"Failed");
private final int mValue;
private final String mStringValue;
private EcCalibratorStatus(int value,String stringValue) {
mValue = value;
values.addElement(this);
mStringValue=stringValue;
}
public static EcCalibratorStatus fromInt(int value) {
for (int i=0; i<values.size();i++) {
EcCalibratorStatus status = (EcCalibratorStatus) values.elementAt(i);
if (status.mValue == value) return status;
}
throw new RuntimeException("status not found ["+value+"]");
}
public String toString() {
return mStringValue;
}
public int value(){
return mValue;
}
}
/**
* clear all added proxy configs
*/
@ -298,12 +343,12 @@ public interface LinphoneCore {
* @param network state
*
*/
public void setNetworkStateReachable(boolean isReachable);
public void setNetworkReachable(boolean isReachable);
/**
*
* @return if false, there is no network connection.
*/
public boolean getNetworkStateReachable();
public boolean isNetworkReachable();
/**
* destroy linphone core and free all underlying resources
*/
@ -492,4 +537,22 @@ public interface LinphoneCore {
public void setPreferredVideoSize(VideoSize vSize);
public VideoSize getPreferredVideoSize();
public PayloadType[] listVideoCodecs();
/**
* enable signaling keep alive. small udp packet sent periodically to keep udp NAT association
*/
void enableKeepAlive(boolean enable);
/**
* get keep elive mode
* @return true if enable
*/
boolean isKeepAliveEnabled();
/**
* Start an echo calibration of the sound devices, in order to find adequate settings for the echo canceler automatically.
* status is notified to {@link LinphoneCoreListener#ecCalibrationStatus(EcCalibratorStatus, int, Object)}
* @param User object
* @throws LinphoneCoreException if operation is still in progress;
**/
void startEchoCalibration(Object data) throws LinphoneCoreException;
}

View file

@ -21,7 +21,7 @@ package org.linphone.core;
@SuppressWarnings("unchecked")
abstract public class LinphoneCoreFactory {
private static String factoryName = "org.linphone.core.LinphoneCoreFactoryImpl";

View file

@ -78,5 +78,14 @@ public interface LinphoneCoreListener {
* @param message incoming message
*/
public void textReceived(LinphoneCore lc, LinphoneChatRoom cr,LinphoneAddress from,String message);
/**
* Invoked when echo cancalation calibration is completed
* @param lc LinphoneCore
* @param status
* @param delay_ms echo delay
* @param data
*/
void ecCalibrationStatus(LinphoneCore lc,LinphoneCore.EcCalibratorStatus status, int delay_ms, Object data);
}

View file

@ -27,6 +27,7 @@ import java.util.Vector;
*
*
*/
@SuppressWarnings("unchecked")
public interface LinphoneFriend {
/**
* Enum controlling behavior for incoming subscription request.

View file

@ -112,5 +112,25 @@ public interface LinphoneProxyConfig {
* @return the route set for this proxy configuration.
*/
public String getRoute();
/**
* Indicates either or not, PUBLISH must be issued for this #LinphoneProxyConfig .
* <br> In case this #LinphoneProxyConfig has been added to #LinphoneCore, follows the linphone_proxy_config_edit() rule.
* @param obj object pointer
* @param val if true, publish will be engaged
*
*/
public void enablePublish(boolean enable);
/**
* returns publish state for this proxy config (see {@link #enablePublish(boolean)} )
*/
public boolean publishEnabled();
LinphoneCore.RegistrationState getState();
/**
* Sets the registration expiration time.
* @param delay expiration time in seconds
*/
void setExpires(int delay);
}

View file

@ -25,6 +25,7 @@ import java.util.Vector;
* Enum describing remote friend status
*
*/
@SuppressWarnings("unchecked")
public class OnlineStatus {
static private Vector values = new Vector();

View file

@ -20,4 +20,5 @@ package org.linphone.core;
public interface PayloadType {
String getMime();
}

View file

@ -25,29 +25,27 @@ public final class VideoSize {
public static final int QCIF = 0;
public static final int CIF = 1;
public static final int HVGA = 2;
public static final int QVGA = 3;
private int width;
public int getWidth() {return width;}
public void setWidth(int width) {this.width = width;}
private int height;
public int getHeight() {return height;}
public void setHeight(int height) {this.height = height;}
public int width;
public int height;
public VideoSize() {}
private VideoSize(int width, int height) {
public VideoSize(int width, int height) {
this.width = width;
this.height = height;
}
public static final VideoSize createStandard(int code) {
public static final VideoSize createStandard(int code, boolean inverted) {
switch (code) {
case QCIF:
return new VideoSize(176, 144);
return inverted? new VideoSize(144, 176) : new VideoSize(176, 144);
case CIF:
return new VideoSize(352, 288);
return inverted? new VideoSize(288, 352) : new VideoSize(352, 288);
case HVGA:
return new VideoSize(320, 480);
return inverted? new VideoSize(320,480) : new VideoSize(480, 320);
case QVGA:
return inverted? new VideoSize(240, 320) : new VideoSize(320, 240);
default:
return new VideoSize(); // Invalid one
}
@ -80,5 +78,15 @@ public final class VideoSize {
return true;
}
@Override
public String toString() {
return "width = "+width + " height = " + height;
}
public boolean isPortrait() {
return height >= width;
}
public VideoSize createInverted() {
return new VideoSize(height, width);
}
}

View file

@ -19,6 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
package org.linphone.core;
@SuppressWarnings("serial")
public class LinphoneCoreException extends Exception {
public LinphoneCoreException() {

View file

@ -1,10 +1,10 @@
./bin/avcodec-52.dll
./bin/avformat-52.dll
./bin/avutil-50.dll
./bin/libeXosip2-4.dll
./bin/libeXosip2-6.dll
./bin/libogg.dll
./bin/libtheora.dll
./bin/libxml2-2.dll
./bin/libosip2-4.dll
./bin/libosipparser2-4.dll
./bin/libosip2-6.dll
./bin/libosipparser2-6.dll
./bin/swscale-0.dll

@ -1 +1 @@
Subproject commit 28a6e7f22fbdd93a01676fc9cc47a2605c846d75
Subproject commit b9a6dad7339175e894d1a0f291ccb5d1143e3199

2
oRTP

@ -1 +1 @@
Subproject commit 7faf69b5eb260ae82ef1efbc49713ccedac7d737
Subproject commit 4e61d05db02318f44768458a69f29faec75c94c8

View file

@ -73,3 +73,6 @@ mediastreamer2/src/itc.c
mediastreamer2/src/extdisplay.c
mediastreamer2/src/msiounit.c
mediastreamer2/src/x11video.c
mediastreamer2/src/msandroid.cpp
mediastreamer2/src/msandroidvideo.cpp

View file

@ -1 +1,2 @@
gtk/p2pwizard.ui

1524
po/cs.po

File diff suppressed because it is too large Load diff

1459
po/de.po

File diff suppressed because it is too large Load diff

1417
po/es.po

File diff suppressed because it is too large Load diff

1465
po/fr.po

File diff suppressed because it is too large Load diff

1460
po/hu.po

File diff suppressed because it is too large Load diff

1578
po/it.po

File diff suppressed because it is too large Load diff

1412
po/ja.po

File diff suppressed because it is too large Load diff

1466
po/nl.po

File diff suppressed because it is too large Load diff

1411
po/pl.po

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

1647
po/ru.po

File diff suppressed because it is too large Load diff

1542
po/sv.po

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -8,7 +8,7 @@ LINPHONE_RINGS=rings/orig.wav \
rings/oldphone-mono-30s.caf \
rings/rock.wav \
rings/bigben.wav \
rings/toy.wav \
rings/toy-mono.wav \
rings/sweet.wav \
rings/synth.wav \
rings/tapping.wav

BIN
share/rings/toy-mono.wav Normal file

Binary file not shown.

Binary file not shown.