diff --git a/CMakeLists.txt b/CMakeLists.txt index ae3952338..c9a1db469 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,18 +1,102 @@ -cmake_minimum_required(VERSION 2.6) -project(LINPHONE C) +############################################################################ +# CMakeLists.txt +# Copyright (C) 2014 Belledonne Communications, Grenoble France +# +############################################################################ +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################ + +cmake_minimum_required(VERSION 2.8.12) +project(LINPHONE C CXX) + + +set(LINPHONE_MAJOR_VERSION "3") +set(LINPHONE_MINOR_VERSION "7") +set(LINPHONE_MICRO_VERSION "0") +set(LINPHONE_VERSION "${LINPHONE_MAJOR_VERSION}.${LINPHONE_MINOR_VERSION}.${LINPHONE_MICRO_VERSION}") +set(LINPHONE_SO_VERSION "6") + + +include(CMakeDependentOption) + +option(ENABLE_STATIC "Build static library (default is shared library)." NO) +option(ENABLE_CONSOLE_UI "Turn on or off compilation of console interface." YES) +option(ENABLE_DATE "Use build date in internal version number." NO) +option(ENABLE_GTK_UI "Turn on or off compilation of gtk interface." YES) +option(ENABLE_LDAP "Enable LDAP support." NO) +option(ENABLE_MSG_STORAGE "Turn on compilation of message storage." YES) +option(ENABLE_NOTIFY "Enable libnotify support." YES) +option(ENABLE_RELATIVE_PREFIX "Find resources relatively to the installation directory." NO) +option(ENABLE_TOOLS "Turn on or off compilation of console interface" YES) +option(ENABLE_TUNNEL "Turn on compilation of tunnel support." NO) +option(ENABLE_TUTORIALS "Enable compilation of tutorials." YES) +option(ENABLE_UNIT_TESTS "Enable compilation of unit tests." YES) +option(ENABLE_UPNP "Build with uPnP support." YES) +option(ENABLE_VIDEO "Build with video support." YES) +cmake_dependent_option(ENABLE_ASSISTANT "Turn on assistant compiling." YES "ENABLE_GTK_UI" NO) + + +list(APPEND CMAKE_MODULE_PATH ${CMAKE_PREFIX_PATH}/share/cmake/Modules) + +include(CheckIncludeFile) + +if(MSVC) + list(APPEND CMAKE_REQUIRED_INCLUDES ${CMAKE_PREFIX_PATH}/include/MSVC) +endif() + +find_package(BelleSIP REQUIRED) +find_package(MS2 REQUIRED) +find_package(XML2 REQUIRED) -option(LINPHONE_ENABLE_VIDEO "Build linphone with video support." ON) include_directories( include/ coreapi/ + ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/coreapi/ + ${BELLESIP_INCLUDE_DIRS} + ${MS2_INCLUDE_DIRS} + ${XML2_INCLUDE_DIRS} ) -include_directories( - ${CMAKE_INSTALL_PREFIX}/include - ${CMAKE_INSTALL_PREFIX}/include/libxml2 -) +if(MSVC) + include_directories(${CMAKE_PREFIX_PATH}/include/MSVC) +endif() + + +if(ENABLE_RELATIVE_PREFIX) + set(LINPHONE_DATA_DIR ".") +else() + set(LINPHONE_DATA_DIR "${CMAKE_INSTALL_PREFIX}") +endif() +set(LINPHONE_PLUGINS_DIR "${LINPHONE_DATA_DIR}/lib/liblinphone/plugins") +set(PACKAGE_LOCALE_DIR "${LINPHONE_DATA_DIR}/share/locale") +set(PACKAGE_DATA_DIR "${LINPHONE_DATA_DIR}/share") +set(PACKAGE_SOUND_DIR "${LINPHONE_DATA_DIR}/share/sounds/linphone") +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h) +set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/config.h PROPERTIES GENERATED ON) +add_definitions(-DHAVE_CONFIG_H) + add_subdirectory(coreapi) add_subdirectory(share) + + +install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/FindLinphone.cmake + DESTINATION share/cmake/Modules + PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ +) diff --git a/FindLinphone.cmake b/FindLinphone.cmake new file mode 100644 index 000000000..6c6871330 --- /dev/null +++ b/FindLinphone.cmake @@ -0,0 +1,74 @@ +############################################################################ +# FindLinphone.txt +# Copyright (C) 2014 Belledonne Communications, Grenoble France +# +############################################################################ +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################ +# +# - Find the linphone include file and library +# +# LINPHONE_FOUND - system has linphone +# LINPHONE_INCLUDE_DIRS - the linphone include directory +# LINPHONE_LIBRARIES - The libraries needed to use linphone +# LINPHONE_CPPFLAGS - The compilation flags needed to use linphone +# LINPHONE_LDFLAGS - The linking flags needed to use linphone + +find_package(ORTP REQUIRED) +find_package(MS2 REQUIRED) +find_package(XML2 REQUIRED) +find_package(BelleSIP REQUIRED) + +set(_LINPHONEROOT_PATHS + ${WITH_LINPHONE} + ${CMAKE_INSTALL_PREFIX} +) + +find_path(LINPHONE_INCLUDE_DIRS + NAMES linphone/linphonecore.h + HINTS _LINPHONE_ROOT_PATHS + PATH_SUFFIXES include +) + +if(LINPHONE_INCLUDE_DIRS) + set(HAVE_LINPHONE_LINPHONECORE_H 1) +endif() + +find_library(LINPHONE_LIBRARIES + NAMES linphone + HINTS ${_LINPHONE_ROOT_PATHS} + PATH_SUFFIXES bin lib +) + +list(APPEND LINPHONE_INCLUDE_DIRS ${ORTP_INCLUDE_DIRS} ${MS2_INCLUDE_DIRS} ${XML2_INCLUDE_DIRS} ${BELLESIP_INCLUDE_DIRS}) +list(APPEND LINPHONE_LIBRARIES ${ORTP_LIBRARIES} ${MS2_LIBRARIES} ${XML2_LIBRARIES} ${BELLESIP_LIBRARIES}) +if(WIN32) + list(APPEND LINPHONE_LIBRARIES shlwapi) +endif(WIN32) + +list(REMOVE_DUPLICATES LINPHONE_INCLUDE_DIRS) +list(REMOVE_DUPLICATES LINPHONE_LIBRARIES) +set(LINPHONE_CPPFLAGS "${MS2_CPPFLAGS}") +set(LINPHONE_LDFLAGS "${MS2_LDFLAGS} ${BELLESIP_LDFLAGS}") + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(Linphone + DEFAULT_MSG + LINPHONE_INCLUDE_DIRS LINPHONE_LIBRARIES +) + +mark_as_advanced(LINPHONE_INCLUDE_DIRS LINPHONE_LIBRARIES LINPHONE_CPPFLAGS LINPHONE_LDFLAGS) diff --git a/README b/README index a2fe5301e..e10ecc2d2 100644 --- a/README +++ b/README @@ -33,10 +33,13 @@ This is Linphone, a free (GPL) video softphone based on the SIP protocol. Here is the command line to get these dependencies installed for Ubuntu && Debian - $ sudo apt-get install libtool intltool libgtk2.0-dev libspeexdsp-dev libavcodec-dev libswscale-dev libx11-dev libxv-dev libgl1-mesa-dev libglew1.6-dev libv4l-dev libxml2-dev + $ sudo apt-get install libtool intltool libgtk2.0-dev libspeexdsp-dev \ +libavcodec-dev libswscale-dev libx11-dev libxv-dev libgl1-mesa-dev \ +libglew1.6-dev libv4l-dev libxml2-dev + for optional library - $ sudo apt-get install libreadline-dev libgsm1-dev libtheora-dev libsoup2.4-dev libsqlite3-dev libupnp4-dev + $ sudo apt-get install libreadline-dev libgsm1-dev libtheora-dev \ +libsoup2.4-dev libsqlite3-dev libupnp4-dev + Install srtp (optional) for call encryption : $ git clone git://git.linphone.org/srtp.git diff --git a/README.macos b/README.macos index 05a00e080..e3ffb72d5 100644 --- a/README.macos +++ b/README.macos @@ -4,6 +4,7 @@ You need: - Xcode (download from apple or using appstore application) + - Java SE - Macports: http://www.macports.org/ Download and install macports using its user friendly installer. @@ -17,7 +18,7 @@ You need: $ sudo port install automake autoconf libtool intltool wget cunit - Install some linphone dependencies with macports - $ sudo port install antlr3 speex libvpx readline sqlite3 libsoup openldap + $ sudo port install antlr3 speex libvpx readline sqlite3 libsoup openldap libupnp $ sudo port install ffmpeg-devel -gpl2 - Install gtk. It is recommended to use the quartz backend for better integration. diff --git a/README.mingw b/README.mingw index 79e8ce547..57c0851c4 100644 --- a/README.mingw +++ b/README.mingw @@ -4,20 +4,20 @@ Software to install Download lastest mingw-get-setup.exe from http://www.mingw.org Run mingw-get-setup.exe. In the package list, select and install: -* mingw32-developer-tool +* mingw-developer-toolkit * mingw32-base * mingw32-gcc-g++ +* mingw32-pthreads-w32 * msys-base +* msys-zip +* msys-unzip +* msys-wget For more information: http://www.mingw.org/wiki/Getting_Started In mingw shell (also refered as msys), run -mingw-get install msys-zip -mingw-get install msys-unzip -mingw-get install msys-wget - mkdir -p /opt/perl/bin cp /bin/perl /opt/perl/bin/. @@ -29,7 +29,7 @@ Download lastest linphone-deps-win32 zip from http://download.savannah.gnu.org/releases-noredirect/linphone/misc using your browser. -Download lastest gtk+-2.24.10 win32 _bundle_ from http://www.gtk.org +Download gtk+-2.24.10 win32 _bundle_ from http://www.gtk.org, direct link: http://ftp.gnome.org/pub/gnome/binaries/win32/gtk+/2.24/gtk+-bundle_2.24.10-20120208_win32.zip Install all these three package in /: @@ -48,7 +48,7 @@ libintl.a libintl.la libintl.dll.a * Download and install Inno Setup Compiler (required only if you run 'make setup.exe'). Add it to your windows Path environment variable. -* Install msys-git from (http://code.google.com/p/msysgit/). During installation you are asked to make a choice about how line endings are treated by git. Choose "Checkout line endings as they are, commit as they are". THIS CHOICE IS VERY IMPORTANT. OTHERS BREAK AUTOMAKE. +* Install msys-git from (http://msysgit.github.io/). During installation you are asked to make a choice about how line endings are treated by git. Choose "Checkout line endings as they are, commit as they are". THIS CHOICE IS VERY IMPORTANT. OTHERS BREAK AUTOMAKE. General rules for compilation @@ -63,6 +63,7 @@ cd /c/sources Building belle-sip ****************** + * make sure that java version 1.6 is available in the PATH. java-1.7 will not work with antlr generator. * download the sources with msys-git shell using the following command: $ git clone git://git.linphone.org/belle-sip.git * compile and install @@ -98,7 +99,8 @@ Building plugins (optional) *************************** This the example for msx264 (H264 plugin), the same applies for other linphone plugins. - $ cd mediastreamer2/plugins/msx264 + $ git clone git://git.linphone.org/msx264.git + $ cd msx264 $ ./autogen.sh $ PKG_CONFIG_PATH=/usr/lib/pkgconfig ./configure --prefix=/usr --enable-shared --disable-static #make a binary zip of this plugin diff --git a/build/android/Android.mk b/build/android/Android.mk index 8f512790c..949eed600 100755 --- a/build/android/Android.mk +++ b/build/android/Android.mk @@ -65,11 +65,14 @@ LOCAL_SRC_FILES := \ xml2lpc.c \ lpc2xml.c \ remote_provisioning.c \ + quality_reporting.c \ + call_log.c \ + call_params.c \ lime.c \ - quality_reporting.c + player.c -ifndef LINPHONE_VERSION -LINPHONE_VERSION = "Devel" +ifndef LIBLINPHONE_VERSION +LIBLINPHONE_VERSION = "Devel" endif LOCAL_CFLAGS += \ @@ -78,7 +81,7 @@ LOCAL_CFLAGS += \ -DINET6 \ -DENABLE_TRACE \ -DHAVE_CONFIG_H \ - -DLINPHONE_VERSION=\"$(LINPHONE_VERSION)\" \ + -DLIBLINPHONE_VERSION=\"$(LIBLINPHONE_VERSION)\" \ -DLINPHONE_PLUGINS_DIR=\"\\tmp\" \ -DUSE_BELLESIP diff --git a/build/android/liblinphone_gitversion.h b/build/android/liblinphone_gitversion.h deleted file mode 100644 index 50e8a106e..000000000 --- a/build/android/liblinphone_gitversion.h +++ /dev/null @@ -1 +0,0 @@ -#define LIBLINPHONE_GIT_VERSION "unknown" diff --git a/build/android/liblinphone_tester.mk b/build/android/liblinphone_tester.mk index e9a2c8718..a6a2ab5f5 100644 --- a/build/android/liblinphone_tester.mk +++ b/build/android/liblinphone_tester.mk @@ -13,7 +13,8 @@ common_SRC_FILES := \ flexisip_tester.c \ tester.c \ remote_provisioning_tester.c \ - quality_reporting_tester.c + quality_reporting_tester.c \ + transport_tester.c common_C_INCLUDES += \ $(LOCAL_PATH) \ @@ -32,6 +33,10 @@ LOCAL_C_INCLUDES = $(common_C_INCLUDES) LOCAL_CFLAGS = -DIN_LINPHONE LOCAL_LDLIBS := -llog +ifeq ($(BUILD_MATROSKA), 1) +LOCAL_CFLAGS += -DHAVE_MATROSKA +endif + LOCAL_SHARED_LIBRARIES := cunit liblinphone include $(BUILD_SHARED_LIBRARY) diff --git a/build/wp8/LibLinphone.vcxproj b/build/wp8/LibLinphone.vcxproj index 797b2517d..8b0660688 100644 --- a/build/wp8/LibLinphone.vcxproj +++ b/build/wp8/LibLinphone.vcxproj @@ -107,6 +107,8 @@ + + @@ -124,6 +126,7 @@ + diff --git a/build/wp8/LibLinphoneTester-native/LibLinphoneTester-native.vcxproj b/build/wp8/LibLinphoneTester-native/LibLinphoneTester-native.vcxproj index 424044515..0512be517 100644 --- a/build/wp8/LibLinphoneTester-native/LibLinphoneTester-native.vcxproj +++ b/build/wp8/LibLinphoneTester-native/LibLinphoneTester-native.vcxproj @@ -105,6 +105,7 @@ + true @@ -153,4 +154,4 @@ - \ No newline at end of file + diff --git a/config.h.cmake b/config.h.cmake new file mode 100644 index 000000000..f348cf3f9 --- /dev/null +++ b/config.h.cmake @@ -0,0 +1,32 @@ +/*************************************************************************** +* config.h.cmake +* Copyright (C) 2014 Belledonne Communications, Grenoble France +* +**************************************************************************** +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +****************************************************************************/ + +#define LINPHONE_MAJOR_VERSION ${LINPHONE_MAJOR_VERSION} +#define LINPHONE_MINOR_VERSION ${LINPHONE_MINOR_VERSION} +#define LINPHONE_MICRO_VERSION ${LINPHONE_MICRO_VERSION} +#define LINPHONE_VERSION "${LINPHONE_VERSION}" +#define LIBLINPHONE_VERSION "${LINPHONE_VERSION}" + +#define LINPHONE_PLUGINS_DIR "${LINPHONE_PLUGINS_DIR}" +#define PACKAGE_LOCALE_DIR "${PACKAGE_LOCALE_DIR}" +#define PACKAGE_DATA_DIR "${PACKAGE_DATA_DIR}" +#define PACKAGE_SOUND_DIR "${PACKAGE_SOUND_DIR}" diff --git a/configure.ac b/configure.ac index 092b41129..f584f5b9a 100644 --- a/configure.ac +++ b/configure.ac @@ -36,7 +36,7 @@ m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],) AC_SUBST([docdir], [${datadir}/doc]) AC_CONFIG_HEADERS(config.h) AC_CONFIG_MACRO_DIR([m4]) -dnl don't put anythingelse before AC_PROG_CC unless checking if macro still work for clang +dnl do not put anythingelse before AC_PROG_CC unless checking if macro still work for clang AC_PROG_CXX(["xcrun clang++" g++]) AC_PROG_CC(["xcrun clang" gcc]) @@ -135,7 +135,7 @@ AC_DEFINE_UNQUOTED(LINPHONE_ALL_LANGS, "$ALL_LINGUAS", [All supported languages] if test "$mingw_found" != "yes" ; then dnl gettext macro does not work properly under mingw. And we want to use the one provided by GTK. - + dnl AM_GNU_GETTEXT pollutes CPPFLAGS: workaround this. CPPFLAGS_save=$CPPFLAGS AM_GNU_GETTEXT([external]) @@ -185,29 +185,29 @@ if test "$enable_ldap" = "true"; then [AC_MSG_ERROR([You need libldap for LDAP support])] ) AC_CHECK_HEADERS(ldap.h, [foo=bar], [AC_MSG_ERROR( [ldap.h not found] ) ] ) - found_ldap=yes + found_ldap=yes fi - + PKG_CHECK_MODULES(SASL, [libsasl2],[found_sasl=yes],[found_sasl=no] ) - + if test "$found_sasl" = "no"; then AC_CHECK_LIB(sasl2, sasl_client_init , [SASL_LIBS="-lsasl2"], [AC_MSG_ERROR([You need SASL for LDAP support] ) ] ) AC_CHECK_HEADERS(sasl/sasl.h,foo=bar, [AC_MSG_ERROR([sasl/sasl.h not found])]) - found_sasl=yes + found_sasl=yes fi - + AC_SUBST(LDAP_CFLAGS) AC_SUBST(LDAP_LIBS) - + AC_SUBST(SASL_CFLAGS) AC_SUBST(SASL_LIBS) - + if test "$found_ldap$found_sasl" = "yesyes"; then AC_DEFINE(BUILD_LDAP,1,[Defined if LDAP build option enabled]) else - AC_MSG_ERROR([Can't use LDAP due to previous errors]) + AC_MSG_ERROR([Cannot use LDAP due to previous errors]) fi fi @@ -248,7 +248,7 @@ AC_ARG_ENABLE(upnp, ) if test "$build_upnp" != "false" ; then - PKG_CHECK_MODULES([LIBUPNP], [libupnp], + PKG_CHECK_MODULES([LIBUPNP], [libupnp], [if pkg-config --atleast-version=1.6 "libupnp < 1.7"; then build_upnp=true else @@ -277,7 +277,7 @@ fi AM_CONDITIONAL(BUILD_TOOLS, test x$build_tools != xfalse) if test "$build_tools" != "false" ; then build_tools=true - AC_DEFINE(BUILD_TOOLS, 1, [Define if tools enabled] ) + AC_DEFINE(BUILD_TOOLS, 1, [Define if tools enabled] ) fi dnl conditionnal build of gtk interface. @@ -537,7 +537,7 @@ fi dnl conditionnal build of video support AC_ARG_ENABLE(video, - [AS_HELP_STRING([--enable-video], [Turn on video support compiling])], + [AS_HELP_STRING([--enable-video], [Turn on video support compiling (default=yes)])], [case "${enableval}" in yes) video=true ;; no) video=false ;; @@ -553,10 +553,10 @@ AC_ARG_WITH(ffmpeg, ) if test "$video" = "true"; then - + if test "$enable_x11" = "true"; then AC_CHECK_HEADERS(X11/Xlib.h) - if test "$build_macos" = "yes"; then + if test "$build_macos" = "yes"; then X11_LIBS="-L/usr/X11/lib -lX11" else AC_CHECK_LIB(X11,XUnmapWindow, X11_LIBS="-lX11") @@ -644,7 +644,7 @@ AC_SUBST(LIBSOUP_LIBS) AM_CONDITIONAL(BUILD_WIZARD, test x$build_wizard != xfalse) if test "$build_wizard" != "false" ; then build_wizard=true - AC_DEFINE(BUILD_WIZARD, 1, [Define if wizard enabled] ) + AC_DEFINE(BUILD_WIZARD, 1, [Define if wizard enabled] ) fi AC_CHECK_HEADERS(libudev.h) @@ -656,27 +656,42 @@ AC_CHECK_LIB(udev,udev_new) AC_ARG_ENABLE(strict, - AC_HELP_STRING([--enable-strict], [Build with stricter options (gcc only) @<:@yes@:>@]), + AC_HELP_STRING([--enable-strict], [Build with stricter options @<:@yes@:>@]), [strictness="${enableval}"], [strictness=yes] ) -STRICT_OPTIONS="-Wall" +STRICT_OPTIONS="-Wall -Wuninitialized" +STRICT_OPTIONS_CC="-Wdeclaration-after-statement " +STRICT_OPTIONS_CXX="" #for clang -case $CC in +case $CC in *clang*) - STRICT_OPTIONS="$STRICT_OPTIONS -Qunused-arguments" + STRICT_OPTIONS="$STRICT_OPTIONS -Qunused-arguments " + #disabled due to wrong optimization false positive with small string + #(cf. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=35903) + STRICT_OPTIONS="$STRICT_OPTIONS -Wno-array-bounds " + ;; +esac +# because Darwin's gcc is actually clang, we need to check it... +case "$target_os" in + *darwin*) + STRICT_OPTIONS="$STRICT_OPTIONS -Wno-error=unknown-warning-option -Qunused-arguments -Wno-tautological-compare -Wno-unused-function " + #disabled due to wrong optimization false positive with small string + #(cf. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=35903) + STRICT_OPTIONS="$STRICT_OPTIONS -Wno-array-bounds " ;; esac - if test "$strictness" = "yes" ; then STRICT_OPTIONS="$STRICT_OPTIONS -Werror" CFLAGS="$CFLAGS -fno-strict-aliasing" fi AC_SUBST(STRICT_OPTIONS) +AC_SUBST(STRICT_OPTIONS_CC) +AC_SUBST(STRICT_OPTIONS_CXX) top_srcdir=`dirname $0` @@ -783,13 +798,13 @@ if test x$enable_msg_storage != xfalse; then fi enable_msg_storage=false fi - + AC_SUBST(SQLITE3_CFLAGS) AC_SUBST(SQLITE3_LIBS) fi - + PKG_CHECK_MODULES(BELLESIP, [belle-sip >= 1.3.1]) SIPSTACK_CFLAGS="$BELLESIP_CFLAGS" @@ -887,7 +902,7 @@ AC_PATH_PROG(DOXYGEN,doxygen,false) AM_CONDITIONAL(HAVE_DOXYGEN, test $DOXYGEN != false) -AC_CONFIG_FILES([ +AC_CONFIG_FILES([ Makefile build/Makefile build/macos/Makefile diff --git a/console/Makefile.am b/console/Makefile.am index 314f5d612..482948329 100644 --- a/console/Makefile.am +++ b/console/Makefile.am @@ -3,12 +3,13 @@ AM_CPPFLAGS=\ -I$(top_srcdir) \ -I$(top_srcdir)/coreapi \ - -I$(top_srcdir)/include + -I$(top_srcdir)/include COMMON_CFLAGS=\ -DIN_LINPHONE \ -D_ORTP_SOURCE \ $(STRICT_OPTIONS) \ + $(STRICT_OPTIONS_CC) \ $(ORTP_CFLAGS) \ $(MEDIASTREAMER_CFLAGS) \ $(VIDEO_CFLAGS) \ diff --git a/console/commands.c b/console/commands.c index 009d8724b..7c5b519d8 100644 --- a/console/commands.c +++ b/console/commands.c @@ -515,7 +515,7 @@ lpc_cmd_help(LinphoneCore *lc, char *arg) i=0; while (advanced_commands[i].help) { - linphonec_out("%10.10s\t%s\n", advanced_commands[i].name, + linphonec_out("%20.20s\t%s\n", advanced_commands[i].name, advanced_commands[i].help); i++; } @@ -603,6 +603,7 @@ lpc_cmd_chat(LinphoneCore *lc, char *args) char *arg1 = args; char *arg2 = NULL; char *ptr = args; + LinphoneChatRoom *cr; if (!args) return 0; @@ -619,7 +620,7 @@ lpc_cmd_chat(LinphoneCore *lc, char *args) /* missing one parameter */ return 0; } - LinphoneChatRoom *cr = linphone_core_create_chat_room(lc,arg1); + cr = linphone_core_create_chat_room(lc,arg1); linphone_chat_room_send_message(cr,arg2); return 1; } @@ -2441,8 +2442,9 @@ static void lpc_display_call_states(LinphoneCore *lc){ }else{ for(;elem!=NULL;elem=elem->next){ const char *flag; + bool_t in_conference; call=(LinphoneCall*)elem->data; - bool_t in_conference=linphone_call_params_get_local_conference_mode(linphone_call_get_current_params(call)); + in_conference=linphone_call_params_get_local_conference_mode(linphone_call_get_current_params(call)); tmp=linphone_call_get_remote_address_as_string (call); flag=in_conference ? "conferencing" : ""; flag=linphone_call_has_transfer_pending(call) ? "transfer pending" : flag; diff --git a/console/linphonec.c b/console/linphonec.c index b8072e325..1a800fd2b 100644 --- a/console/linphonec.c +++ b/console/linphonec.c @@ -367,8 +367,8 @@ static void linphonec_call_state_changed(LinphoneCore *lc, LinphoneCall *call, L if ( auto_answer) { answer_call=TRUE; } else if (real_early_media_sending) { - linphonec_out("Sending early media using real hardware\n"); LinphoneCallParams* callparams = linphone_core_create_default_call_parameters(lc); + linphonec_out("Sending early media using real hardware\n"); linphone_call_params_enable_early_media_sending(callparams, TRUE); if (vcap_enabled) linphone_call_params_enable_video(callparams, TRUE); linphone_core_accept_early_media_with_params(lc, call, callparams); @@ -536,6 +536,7 @@ char *linphonec_readline(char *prompt){ fprintf(stdout,"%s",prompt); fflush(stdout); while(1){ + ms_mutex_lock(&prompt_mutex); if (have_prompt){ char *ret=strdup(received_prompt); @@ -546,15 +547,17 @@ char *linphonec_readline(char *prompt){ ms_mutex_unlock(&prompt_mutex); linphonec_idle_call(); #ifdef WIN32 - Sleep(20); - /* Following is to get the video window going as it - should. Maybe should we only have this on when the option -V - or -D is on? */ - MSG msg; + { + MSG msg; + Sleep(20); + /* Following is to get the video window going as it + should. Maybe should we only have this on when the option -V + or -D is on? */ - if (PeekMessage(&msg, NULL, 0, 0,1)) { - TranslateMessage(&msg); - DispatchMessage(&msg); + if (PeekMessage(&msg, NULL, 0, 0,1)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } } #else usleep(20000); @@ -747,7 +750,7 @@ linphonec_init(int argc, char **argv) linphone_core_enable_video_display(linphonec, display_enabled); if (display_enabled && window_id != 0) { - printf ("Setting window_id: 0x%x\n", window_id); + printf("Setting window_id: 0x%x\n", window_id); linphone_core_set_native_video_window_id(linphonec,window_id); } @@ -828,12 +831,13 @@ linphonec_prompt_for_auth_final(LinphoneCore *lc) #ifdef HAVE_READLINE rl_hook_func_t *old_event_hook; #endif + LinphoneAuthInfo *pending_auth; if (reentrancy!=0) return 0; reentrancy++; - LinphoneAuthInfo *pending_auth=auth_stack.elem[auth_stack.nitems-1]; + pending_auth=auth_stack.elem[auth_stack.nitems-1]; snprintf(auth_prompt, 256, "Password for %s on %s: ", pending_auth->username, pending_auth->realm); diff --git a/console/shell.c b/console/shell.c index bfc758bf8..016992397 100644 --- a/console/shell.c +++ b/console/shell.c @@ -177,12 +177,14 @@ static void spawn_linphonec(int argc, char *argv[]){ static void spawn_linphonec(int argc, char *argv[]){ PROCESS_INFORMATION pinfo; STARTUPINFO si; + BOOL ret; + ZeroMemory( &si, sizeof(si) ); si.cb = sizeof(si); ZeroMemory( &pinfo, sizeof(pinfo) ); - BOOL ret=CreateProcess(NULL,"linphoned.exe --pipe -c NUL", + ret=CreateProcess(NULL,"linphoned.exe --pipe -c NUL", NULL, NULL, FALSE, diff --git a/coreapi/CMakeLists.txt b/coreapi/CMakeLists.txt index 1fb5f2add..df753c11e 100644 --- a/coreapi/CMakeLists.txt +++ b/coreapi/CMakeLists.txt @@ -1,47 +1,30 @@ +############################################################################ +# CMakeLists.txt +# Copyright (C) 2014 Belledonne Communications, Grenoble France +# +############################################################################ +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################ + if(MSVC) find_library(LIBGCC NAMES gcc) find_library(LIBMINGWEX NAMES mingwex) endif() -find_library(LIBORTP NAMES ortp) -find_library(LIBMEDIASTREAMER_BASE NAMES mediastreamer_base) -find_library(LIBMEDIASTREAMER_VOIP NAMES mediastreamer_voip) -find_library(LIBBELLESIP NAMES bellesip) -find_library(LIBXML2 NAMES xml2) -find_program(GIT git) - -set(GIT_VERSION "unknown") -if(GIT) - execute_process( - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - COMMAND ${GIT} describe --always - OUTPUT_VARIABLE GIT_DESCRIBE - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - execute_process( - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - COMMAND ${GIT} describe --abbrev=0 - OUTPUT_VARIABLE GIT_TAG - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - execute_process( - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - COMMAND ${GIT} rev-parse HEAD - OUTPUT_VARIABLE GIT_REVISION - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - if(GIT_DESCRIBE) - set(GIT_VERSION ${GIT_DESCRIBE}) - else(GIT_DESCRIBE) - if(GIT_REVISION) - set(GIT_VERSION ${GIT_REVISION}) - endif(GIT_REVISION) - endif(GIT_DESCRIBE) -endif(GIT) -execute_process( - COMMAND ${CMAKE_COMMAND} -E echo "#define LIBLINPHONE_GIT_VERSION \"${GIT_VERSION}\"" - OUTPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/liblinphone_gitversion.h -) set(SOURCE_FILES address.c @@ -59,6 +42,8 @@ set(SOURCE_FILES bellesip_sal/sal_op_registration.c bellesip_sal/sal_sdp.c callbacks.c + call_log.c + call_params.c chat.c conference.c ec-calibrator.c @@ -68,7 +53,6 @@ set(SOURCE_FILES info.c linphonecall.c linphonecore.c - #linphone_tunnel.cc linphone_tunnel_stubs.c linphone_tunnel_config.c lpconfig.c @@ -76,6 +60,7 @@ set(SOURCE_FILES message_storage.c misc.c offeranswer.c + player.c presence.c proxy.c quality_reporting.c @@ -83,7 +68,6 @@ set(SOURCE_FILES sal.c siplogin.c sipsetup.c - #TunnelManager.cc xml.c xml2lpc.c bellesip_sal/sal_impl.h @@ -99,55 +83,86 @@ set(SOURCE_FILES sipsetup.h xml2lpc.h ) +if(ENABLE_TUNNEL) + list(APPEND SOURCE_FILES + linphone_tunnel.cc + TunnelManager.cc + ) + add_definitions(-DTUNNEL_ENABLED) +endif() + +set(GENERATED_SOURCE_FILES + ${CMAKE_CURRENT_BINARY_DIR}/liblinphone_gitversion.h +) +set_source_files_properties(${GENERATED_SOURCE_FILES} PROPERTIES GENERATED TRUE) +find_package(Git) +add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/liblinphone_gitversion.h + COMMAND ${CMAKE_COMMAND} -DGIT_EXECUTABLE=${GIT_EXECUTABLE} -DWORK_DIR=${CMAKE_CURRENT_SOURCE_DIR} -DOUTPUT_DIR=${CMAKE_CURRENT_BINARY_DIR} -P ${CMAKE_CURRENT_SOURCE_DIR}/gitversion.cmake) add_definitions( - -D_TRUE_TIME -DIN_LINPHONE -DUSE_BELLESIP - #-DTUNNEL_ENABLED - -DLINPHONE_PACKAGE_NAME="linphone" - -DLINPHONE_VERSION="Devel" -DLIBLINPHONE_EXPORTS - -DLINPHONE_PLUGINS_DIR="" ) -if(LINPHONE_ENABLE_VIDEO) +if(ENABLE_VIDEO) add_definitions(-DVIDEO_ENABLED) -endif(LINPHONE_ENABLE_VIDEO) +endif() -if(WIN32) -add_definitions( - -DWINDOW_NATIVE - /FIliblinphone_gitversion.h +set(LIBS + ${LIBGCC} + ${LIBMINGWEX} + ${BELLESIP_LIBRARIES} + ${MS2_LIBRARIES} + ${XML2_LIBRARIES} ) +if(WIN32) + list(APPEND LIBS shlwapi) +endif() -set(LIBS ws2_32) -endif(WIN32) -set(LIBS ${LIBS} ${LIBGCC} ${LIBMINGWEX} ${LIBORTP} ${LIBMEDIASTREAMER_BASE} ${LIBMEDIASTREAMER_VOIP} ${LIBBELLESIP} ${LIBXML2}) - -add_library(linphone SHARED ${SOURCE_FILES}) -set_target_properties(linphone PROPERTIES VERSION 3.7.0 SOVERSION 5) - -target_link_libraries(linphone ${LIBS}) +if(ENABLE_STATIC) + add_library(linphone STATIC ${SOURCE_FILES} ${GENERATED_SOURCE_FILES}) + target_link_libraries(linphone ${LIBS}) +else() + add_library(linphone SHARED ${SOURCE_FILES} ${GENERATED_SOURCE_FILES}) + set_target_properties(linphone PROPERTIES VERSION ${LINPHONE_VERSION} SOVERSION ${LINPHONE_SO_VERSION} LINKER_LANGUAGE CXX) + target_link_libraries(linphone ${LIBS}) + if(MSVC) + if(CMAKE_BUILD_TYPE STREQUAL "Debug") + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Debug/linphone.pdb + DESTINATION bin + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE + ) + endif() + endif() +endif() install(TARGETS linphone - RUNTIME DESTINATION bin + RUNTIME DESTINATION bin LIBRARY DESTINATION lib ARCHIVE DESTINATION lib - PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE +) -file(GLOB HEADER_FILES "*.h") +set(HEADER_FILES + call_log.h + call_params.h + event.h + linphonecore.h + linphonecore_utils.h + linphonefriend.h + linphonepresence.h + linphone_tunnel.h + lpc2xml.h + lpconfig.h + sipsetup.h + xml2lpc.h +) install(FILES ${HEADER_FILES} DESTINATION include/linphone PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ ) -if(WIN32) -if(CMAKE_BUILD_TYPE STREQUAL "Debug") -install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Debug/linphone.pdb - DESTINATION bin - PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE -) -endif() -endif(WIN32) + +add_subdirectory(help) diff --git a/coreapi/Makefile.am b/coreapi/Makefile.am index 5d5db0f4b..b13f8c5c7 100644 --- a/coreapi/Makefile.am +++ b/coreapi/Makefile.am @@ -5,6 +5,12 @@ GITDESCRIBE=`cd $(top_srcdir) && git describe --always` GIT_TAG=`cd $(top_srcdir) && git describe --abbrev=0` GITREVISION=`cd $(top_srcdir) && git rev-parse HEAD` +## This command is used to check if the sources are cloned in a git repo. +## We can't only depend on the presence of the .git/ directory anymore, +## because of gits submodule handling. +## We now simply issue a git log on configure.ac and if the output is empty (error or file not tracked), then we are not in git. +GITLOG=$(shell git log -1 --pretty=format:%H $(top_srcdir)/configure.ac) + ECHO=/bin/echo SUBDIRS=. help @@ -18,7 +24,7 @@ CLEANFILES=$(GITVERSION_FILE) ## Process this file with automake to produce Makefile.in linphone_includedir=$(includedir)/linphone -linphone_include_HEADERS=linphonecore.h linphonefriend.h linphonepresence.h linphonecore_utils.h lpconfig.h sipsetup.h event.h xml2lpc.h lpc2xml.h linphone_tunnel.h +linphone_include_HEADERS=linphonecore.h linphonefriend.h linphonepresence.h linphonecore_utils.h lpconfig.h sipsetup.h event.h xml2lpc.h lpc2xml.h linphone_tunnel.h call_log.h call_params.h lib_LTLIBRARIES=liblinphone.la @@ -54,12 +60,15 @@ liblinphone_la_SOURCES=\ remote_provisioning.c \ lime.c \ quality_reporting.c quality_reporting.h\ + call_log.c \ + call_params.c \ + player.c \ $(GITVERSION_FILE) if BUILD_UPNP liblinphone_la_SOURCES+=upnp.c upnp.h endif - + liblinphone_la_SOURCES+= bellesip_sal/sal_address_impl.c \ bellesip_sal/sal_impl.c bellesip_sal/sal_impl.h \ bellesip_sal/sal_op_impl.c \ @@ -74,7 +83,7 @@ liblinphone_la_SOURCES+= bellesip_sal/sal_address_impl.c \ bellesip_sal/sal_op_events.c if BUILD_WIZARD -liblinphone_la_SOURCES+=sipwizard.c +liblinphone_la_SOURCES+=sipwizard.c endif liblinphone_la_SOURCES+=linphone_tunnel_config.c @@ -133,8 +142,9 @@ endif AM_CPPFLAGS=\ -I$(top_srcdir) -I$(top_srcdir)/include -I$(builddir) -AM_CFLAGS=\ - $(STRICT_OPTIONS) -DIN_LINPHONE \ +COMMON_CFLAGS=\ + $(STRICT_OPTIONS) \ + -DIN_LINPHONE \ $(ORTP_CFLAGS) \ $(MEDIASTREAMER_CFLAGS) \ $(SIPSTACK_CFLAGS) \ @@ -150,19 +160,20 @@ AM_CFLAGS=\ $(LDAP_CFLAGS) $(SASL_CFLAGS) if BUILD_WIZARD -AM_CFLAGS+= -DBUILD_WIZARD +COMMON_CFLAGS+= -DBUILD_WIZARD endif -AM_CFLAGS+= -DUSE_BELLESIP +COMMON_CFLAGS+= -DUSE_BELLESIP -AM_CXXFLAGS=$(AM_CFLAGS) +AM_CFLAGS=$(COMMON_CFLAGS) $(STRICT_OPTIONS_CC) +AM_CXXFLAGS=$(COMMON_CFLAGS) $(STRICT_OPTIONS_CXX) #Make sure that we are in linphone's git tree by doing git log $(top_srcdir)/configure.ac. -#if it is something known to git, then that will be ok to check the git describe number and make sure it is consistent with +#if it is something known to git, then that will be ok to check the git describe number and make sure it is consistent with #the PACKAGE_VERSION given in configure.ac make_gitversion_h: - if test -d $(top_srcdir)/.git ; then \ + if test -n "$(GITLOG)" ; then \ if test "$(GITDESCRIBE)" != "" ; then \ if test "$(GIT_TAG)" != "$(PACKAGE_VERSION)" ; then \ echo "*** PACKAGE_VERSION and git tag differ. Please put them identical."; \ diff --git a/coreapi/TunnelManager.cc b/coreapi/TunnelManager.cc index 2bc8cd3e0..d88212c68 100644 --- a/coreapi/TunnelManager.cc +++ b/coreapi/TunnelManager.cc @@ -1,7 +1,7 @@ /* * C Implementation: tunnel * - * Description: + * Description: * * * Author: Simon Morlat , (C) 2009 @@ -19,18 +19,17 @@ #ifndef USE_BELLESIP #include "eXosip2/eXosip_transport_hook.h" #endif -#include "tunnel/udp_mirror.hh" #include "private.h" #ifdef ANDROID #include #endif +belledonnecomm::TunnelManager *bcTunnel(const LinphoneTunnel *tunnel); using namespace belledonnecomm; using namespace ::std; - void TunnelManager::addServer(const char *ip, int port,unsigned int udpMirrorPort,unsigned int delay) { if (ip == NULL) { ip = ""; @@ -53,7 +52,6 @@ void TunnelManager::cleanServers() { mServerAddrs.clear(); UdpMirrorClientList::iterator it; - mAutoDetectStarted=false; for (it = mUdpMirrorClients.begin(); it != mUdpMirrorClients.end();) { UdpMirrorClient& s=*it++; s.stop(); @@ -67,11 +65,6 @@ void TunnelManager::reconnect(){ mTunnelClient->reconnect(); } -void TunnelManager::setCallback(StateCallback cb, void *userdata) { - mCallback=cb; - mCallbackData=userdata; -} - static void sCloseRtpTransport(RtpTransport *t, void *userData){ TunnelSocket *s=(TunnelSocket*)userData; TunnelManager *manager=(TunnelManager*)s->getUserPointer(); @@ -79,13 +72,16 @@ static void sCloseRtpTransport(RtpTransport *t, void *userData){ } void TunnelManager::closeRtpTransport(RtpTransport *t, TunnelSocket *s){ mTunnelClient->closeSocket(s); - ms_free(t); } static RtpTransport *sCreateRtpTransport(void* userData, int port){ return ((TunnelManager *) userData)->createRtpTransport(port); } +void sDestroyRtpTransport(RtpTransport *t){ + ms_free(t); +} + RtpTransport *TunnelManager::createRtpTransport(int port){ TunnelSocket *socket=mTunnelClient->createSocket(port); socket->setUserPointer(this); @@ -94,14 +90,15 @@ RtpTransport *TunnelManager::createRtpTransport(int port){ t->t_recvfrom=customRecvfrom; t->t_sendto=customSendto; t->t_close=sCloseRtpTransport; + t->t_destroy=sDestroyRtpTransport; t->data=socket; return t; } -void TunnelManager::start() { - if (!mTunnelClient) { +void TunnelManager::startClient() { + if (mTunnelClient == NULL) { mTunnelClient = new TunnelClient(); - mTunnelClient->setCallback((StateCallback)tunnelCallback,this); + mTunnelClient->setCallback((TunnelClientController::StateCallback)tunnelCallback,this); list::iterator it; for(it=mServerAddrs.begin();it!=mServerAddrs.end();++it){ const ServerAddr &addr=*it; @@ -110,14 +107,23 @@ void TunnelManager::start() { mTunnelClient->setHttpProxy(mHttpProxyHost.c_str(), mHttpProxyPort, mHttpUserName.c_str(), mHttpPasswd.c_str()); } mTunnelClient->start(); + linphone_core_set_rtp_transport_factories(mCore,&mTransportFactories); + if(mTunnelizeSipPackets) { + sal_enable_tunnel(mCore->sal, mTunnelClient); + } } -bool TunnelManager::isStarted() { - return mTunnelClient != 0 && mTunnelClient->isStarted(); +void TunnelManager::stopClient(){ + linphone_core_set_rtp_transport_factories(mCore,NULL); + sal_disable_tunnel(mCore->sal); + if (mTunnelClient){ + delete mTunnelClient; + mTunnelClient=NULL; + } } -bool TunnelManager::isReady() const { - return mTunnelClient && mTunnelClient->isReady() && mReady; +bool TunnelManager::isConnected() const { + return mTunnelClient != NULL && mTunnelClient->isReady(); } int TunnelManager::customSendto(struct _RtpTransport *t, mblk_t *msg , int flags, const struct sockaddr *to, socklen_t tolen){ @@ -135,15 +141,20 @@ int TunnelManager::customRecvfrom(struct _RtpTransport *t, mblk_t *msg, int flag } -TunnelManager::TunnelManager(LinphoneCore* lc) :TunnelClientController() -,mCore(lc) -,mCallback(NULL) -,mEnabled(false) -,mTunnelClient(NULL) -,mAutoDetectStarted(false) -,mReady(false) -,mHttpProxyPort(0){ - +TunnelManager::TunnelManager(LinphoneCore* lc) : + mCore(lc), +#ifndef USE_BELLESIP + mSipSocket(NULL), + mExosipTransport(NULL), +#endif + mMode(LinphoneTunnelModeDisable), + mTunnelClient(NULL), + mIsConnected(false), + mHttpProxyPort(0), + mPreviousRegistrationEnabled(false), + mTunnelizeSipPackets(true), + mVTable(NULL) +{ linphone_core_add_iterate_hook(mCore,(LinphoneCoreIterateHook)sOnIterate,this); mTransportFactories.audio_rtcp_func=sCreateRtpTransport; mTransportFactories.audio_rtcp_func_data=this; @@ -153,104 +164,94 @@ TunnelManager::TunnelManager(LinphoneCore* lc) :TunnelClientController() mTransportFactories.video_rtcp_func_data=this; mTransportFactories.video_rtp_func=sCreateRtpTransport; mTransportFactories.video_rtp_func_data=this; + mVTable = linphone_vtable_new(); + mVTable->network_reachable = networkReachableCb; + linphone_core_add_listener(mCore, mVTable); } TunnelManager::~TunnelManager(){ stopClient(); + linphone_core_remove_listener(mCore, mVTable); + linphone_vtable_destroy(mVTable); } -void TunnelManager::stopClient(){ - sal_disable_tunnel(mCore->sal); - if (mTunnelClient){ - delete mTunnelClient; - mTunnelClient=NULL; +void TunnelManager::registration(){ + // registration occurs always after an unregistation has been made. First we + // need to reset the previous registration mode + LinphoneProxyConfig* lProxy; + linphone_core_get_default_proxy(mCore, &lProxy); + if (lProxy) { + linphone_proxy_config_edit(lProxy); + linphone_proxy_config_enable_register(lProxy,mPreviousRegistrationEnabled); + linphone_proxy_config_done(lProxy); } } void TunnelManager::processTunnelEvent(const Event &ev){ - LinphoneProxyConfig* lProxy; - linphone_core_get_default_proxy(mCore, &lProxy); - - if (mEnabled && mTunnelClient->isReady()){ + if (ev.mData.mConnected){ ms_message("Tunnel is up, registering now"); - linphone_core_set_firewall_policy(mCore,LinphonePolicyNoFirewall); - linphone_core_set_rtp_transport_factories(mCore,&mTransportFactories); - - sal_enable_tunnel(mCore->sal, mTunnelClient); - - //register - if (lProxy) { - linphone_proxy_config_refresh_register(lProxy); - } - mReady=true; - }else if (mEnabled && !mTunnelClient->isReady()){ - /* we got disconnected from the tunnel */ - mReady=false; + registration(); + } else { + ms_error("Tunnel has been disconnected"); } } -void TunnelManager::waitUnRegistration(){ +void TunnelManager::waitUnRegistration() { LinphoneProxyConfig* lProxy; + linphone_core_get_default_proxy(mCore, &lProxy); - if (lProxy && linphone_proxy_config_get_state(lProxy)==LinphoneRegistrationOk) { - int i=0; - linphone_proxy_config_edit(lProxy); - linphone_proxy_config_enable_register(lProxy,FALSE); - linphone_proxy_config_done(lProxy); - //make sure unregister is sent and authenticated - do{ - linphone_core_iterate(mCore); - ms_usleep(20000); - if (i>100){ - ms_message("tunnel: timeout for unregistration expired, giving up"); - break; - } - i++; - }while(linphone_proxy_config_get_state(lProxy)!=LinphoneRegistrationCleared); - } + if (lProxy){ + mPreviousRegistrationEnabled=linphone_proxy_config_register_enabled(lProxy); + if (linphone_proxy_config_is_registered(lProxy)) { + int i=0; + linphone_proxy_config_edit(lProxy); + linphone_proxy_config_enable_register(lProxy,FALSE); + linphone_proxy_config_done(lProxy); + sal_unregister(lProxy->op); + //make sure unregister is sent and authenticated + do{ + linphone_core_iterate(mCore); + ms_usleep(20000); + if (i>100){ + ms_message("tunnel: timeout for unregistration expired, giving up"); + break; + } + i++; + }while(linphone_proxy_config_is_registered(lProxy)); + ms_message("Unregistration %s", linphone_proxy_config_is_registered(lProxy)?"failed":"succeeded"); + }else{ + ms_message("No registration pending"); + } + } } -void TunnelManager::enable(bool isEnable) { - ms_message("Turning tunnel [%s]",(isEnable?"on":"off")); - if (isEnable && !mEnabled){ - mEnabled=true; - //1 save transport and firewall policy - linphone_core_get_sip_transports(mCore, &mRegularTransport); - mPreviousFirewallPolicy=linphone_core_get_firewall_policy(mCore); - //2 unregister +/*Each time tunnel is enabled/disabled, we need to unregister previous session and re-register. Since tunnel initialization +is asynchronous, we temporary disable auto register while tunnel sets up, and reenable it when re-registering. */ +void TunnelManager::setMode(LinphoneTunnelMode mode) { + if(mMode != mode) { waitUnRegistration(); - //3 insert tunnel - start(); - }else if (!isEnable && mEnabled){ - //1 unregister - waitUnRegistration(); - - mEnabled=false; - stopClient(); - mReady=false; - linphone_core_set_rtp_transport_factories(mCore,NULL); - - sal_disable_tunnel(mCore->sal); - // Set empty transports to force the setting of regular transport, otherwise it is not applied - LCSipTransports lTransport; - lTransport.udp_port = 0; - lTransport.tcp_port = 0; - lTransport.tls_port = 0; - lTransport.dtls_port = 0; - linphone_core_set_sip_transports(mCore, &lTransport); - - //Restore transport and firewall policy - linphone_core_set_sip_transports(mCore, &mRegularTransport); - linphone_core_set_firewall_policy(mCore, mPreviousFirewallPolicy); - //register - LinphoneProxyConfig* lProxy; - linphone_core_get_default_proxy(mCore, &lProxy); - if (lProxy) { - linphone_proxy_config_edit(lProxy); - linphone_proxy_config_enable_register(lProxy,TRUE); - linphone_proxy_config_done(lProxy); + switch(mode) { + case LinphoneTunnelModeEnable: + mMode = mode; + startClient(); + /* registration is done by proccessTunnelEvent() when the tunnel + the tunnel succeed to connect */ + break; + case LinphoneTunnelModeDisable: + mMode = mode; + stopClient(); + registration(); + break; + case LinphoneTunnelModeAuto: + mMode = mode; + autoDetect(); + /* Registration is not needed because processUdpMirrorEvent() will + call either connect() or disconnect(). Should disconnect() is called, + processUdpMirrorEvent() care to call registratin() */ + break; + default: + ms_error("TunnelManager::setMode(): invalid mode (%d)", mode); } - } } @@ -320,30 +321,29 @@ void TunnelManager::enableLogs(bool isEnabled,LogHandler logHandler) { SetLogLevel(TUNNEL_ERROR|TUNNEL_WARN); } } - -bool TunnelManager::isEnabled() { - return mEnabled; + +LinphoneTunnelMode TunnelManager::getMode() const { + return mMode; } void TunnelManager::processUdpMirrorEvent(const Event &ev){ if (ev.mData.mHaveUdp) { LOGI("Tunnel is not required, disabling"); - enable(false); - mAutoDetectStarted = false; + stopClient(); + registration(); } else { mCurrentUdpMirrorClient++; if (mCurrentUdpMirrorClient !=mUdpMirrorClients.end()) { // enable tunnel but also try backup server LOGI("Tunnel is required, enabling; Trying backup udp mirror"); - + UdpMirrorClient &lUdpMirrorClient=*mCurrentUdpMirrorClient; lUdpMirrorClient.start(TunnelManager::sUdpMirrorClientCallback,(void*)this); } else { LOGI("Tunnel is required, enabling; no backup udp mirror available"); - mAutoDetectStarted = false; + startClient(); } - enable(true); } } @@ -361,21 +361,22 @@ void TunnelManager::sUdpMirrorClientCallback(bool isUdpAvailable, void* data) { thiz->postEvent(ev); } +void TunnelManager::networkReachableCb(LinphoneCore *lc, bool_t reachable) { + TunnelManager *tunnel = bcTunnel(linphone_core_get_tunnel(lc)); + if(reachable && tunnel->getMode() == LinphoneTunnelModeAuto) { + tunnel->autoDetect(); + } +} + void TunnelManager::autoDetect() { // first check if udp mirrors was provisionned if (mUdpMirrorClients.empty()) { LOGE("No UDP mirror server configured aborting auto detection"); return; } - if (mAutoDetectStarted) { - LOGE("auto detection already in progress, restarting"); - (*mCurrentUdpMirrorClient).stop(); - } - mAutoDetectStarted=true; - mCurrentUdpMirrorClient =mUdpMirrorClients.begin(); + mCurrentUdpMirrorClient = mUdpMirrorClients.begin(); UdpMirrorClient &lUdpMirrorClient=*mCurrentUdpMirrorClient; lUdpMirrorClient.start(TunnelManager::sUdpMirrorClientCallback,(void*)this); - } void TunnelManager::setHttpProxyAuthInfo(const char* username,const char* passwd) { @@ -384,6 +385,22 @@ void TunnelManager::setHttpProxyAuthInfo(const char* username,const char* passwd if (mTunnelClient) mTunnelClient->setHttpProxyAuthInfo(username,passwd); } +void TunnelManager::tunnelizeSipPackets(bool enable){ + if(enable != mTunnelizeSipPackets) { + mTunnelizeSipPackets = enable; + if(isConnected()) { + waitUnRegistration(); + if(mTunnelizeSipPackets) sal_enable_tunnel(mCore->sal, mTunnelClient); + else sal_disable_tunnel(mCore->sal); + registration(); + } + } +} + +bool TunnelManager::tunnelizeSipPacketsEnabled() const { + return mTunnelizeSipPackets; +} + void TunnelManager::setHttpProxy(const char *host,int port, const char *username, const char *passwd){ mHttpUserName=username?username:""; mHttpPasswd=passwd?passwd:""; @@ -392,6 +409,6 @@ void TunnelManager::setHttpProxy(const char *host,int port, const char *username if (mTunnelClient) mTunnelClient->setHttpProxy(host, port, username, passwd); } -LinphoneCore *TunnelManager::getLinphoneCore(){ +LinphoneCore *TunnelManager::getLinphoneCore() const{ return mCore; } diff --git a/coreapi/TunnelManager.hh b/coreapi/TunnelManager.hh index 9ca29ad86..38b6b90e3 100644 --- a/coreapi/TunnelManager.hh +++ b/coreapi/TunnelManager.hh @@ -1,7 +1,7 @@ /* * C Implementation: tunnel * - * Description: + * Description: * * * @@ -12,35 +12,35 @@ #define __TUNNEL_CLIENT_MANAGER_H__ #include #include -#include "tunnel/client.hh" +#include +#include #include "linphonecore.h" +#include "linphone_tunnel.h" #ifndef USE_BELLESIP extern "C" { - #include "eXosip2/eXosip_transport_hook.h" + #include } #endif namespace belledonnecomm { -class TunnelClient; -class UdpMirrorClient; /** - * @addtogroup tunnel_client + * @addtogroup tunnel_client * @{ **/ /** - * The TunnelManager class extends the LinphoneCore functionnality in order to provide an easy to use API to + * The TunnelManager class extends the LinphoneCore functionnality in order to provide an easy to use API to * - provision tunnel servers ip addresses and ports * - start/stop the tunneling service - * - be informed of of connection and disconnection events to the tunnel server + * - be informed of connection and disconnection events to the tunnel server * - perform auto-detection whether tunneling is required, based on a test of sending/receiving a flow of UDP packets. - * + * * It takes in charge automatically the SIP registration procedure when connecting or disconnecting to a tunnel server. * No other action on LinphoneCore is required to enable full operation in tunnel mode. **/ - class TunnelManager : public TunnelClientController{ - + class TunnelManager { + public: /** * Add a tunnel server. At least one should be provided to be able to connect. @@ -61,20 +61,8 @@ class UdpMirrorClient; void addServer(const char *ip, int port,unsigned int udpMirrorPort,unsigned int delay); /** * Removes all tunnel server address previously entered with addServer() - **/ - void cleanServers(); - /** - * Register a state callback to be notified whenever the tunnel client is connected or disconnected to the tunnel server. - * @param cb application callback function to use for notifying of connection/disconnection events. - * @param userdata An opaque pointer passed to the callback, used optionally by the application to retrieve a context. - **/ - void setCallback(StateCallback cb, void *userdata); - /** - * Start connecting to a tunnel server. - * At this step, nothing is tunneled yet. The enable() method must be used to state whether SIP and RTP traffic - * need to be tunneled or not. **/ - void start(); + void cleanServers(); /** * Forces reconnection to the tunnel server. * This method is useful when the device switches from wifi to Edge/3G or vice versa. In most cases the tunnel client socket @@ -83,22 +71,15 @@ class UdpMirrorClient; **/ void reconnect(); /** - * Sets whether tunneling of SIP and RTP is required. - * @param isEnabled If true enter in tunneled mode, if false exits from tunneled mode. - * The TunnelManager takes care of refreshing SIP registration when switching on or off the tunneled mode. - * - **/ - void enable(bool isEnabled); - /** - * In auto detect mode, the tunnel manager try to establish a real time rtp cummunication with the tunnel server on specified port. - *
In case of success, the tunnel is automatically turned off. Otherwise, if no udp commmunication is feasible, tunnel mode is turned on. - *
Call this method each time to run the auto detection algorithm + * @brief setMode + * @param mode */ - void autoDetect(); + void setMode(LinphoneTunnelMode mode); /** - * Returns a boolean indicating whether tunneled operation is enabled. - **/ - bool isEnabled(); + * @brief Return the tunnel mode + * @return #LinphoneTunnelMode + */ + LinphoneTunnelMode getMode() const; /** * Enables debug logs of the Tunnel subsystem. **/ @@ -115,24 +96,52 @@ class UdpMirrorClient; * @param passwd The password. **/ void setHttpProxyAuthInfo(const char* username,const char* passwd); - ~TunnelManager(); + void setHttpProxy(const char *host,int port, const char *username, const char *passwd); + /** + * Indicate to the tunnel manager whether SIP packets must pass + * through the tunnel. That featurte is automatically enabled at + * the creation of the TunnelManager instance. + * @param enable If set to TRUE, SIP packets will pass through the tunnel. + * If set to FALSE, SIP packets will pass by the configured proxies. + */ + void tunnelizeSipPackets(bool enable); + /** + * @brief Check whether the tunnel manager is set to tunnelize SIP packets + * @return True, SIP packets pass through the tunnel + */ + bool tunnelizeSipPacketsEnabled() const; + /** + * @brief Constructor + * @param lc The LinphoneCore instance of which the TunnelManager will be associated to. + */ TunnelManager(LinphoneCore* lc); /** - * Destroy the given RtpTransport. + * @brief Destructor */ - void closeRtpTransport(RtpTransport *t, TunnelSocket *s); - + ~TunnelManager(); /** - * Create an RtpTransport. + * @brief Create an RtpTransport + * @param port + * @return */ RtpTransport *createRtpTransport(int port); - /** - * Get associated Linphone Core. + * @brief Destroy the given RtpTransport + * @param t + * @param s */ - LinphoneCore *getLinphoneCore(); - virtual void setHttpProxy(const char *host,int port, const char *username, const char *passwd); - virtual bool isReady() const; + void closeRtpTransport(RtpTransport *t, TunnelSocket *s); + /** + * @brief Get associated Linphone Core + * @return pointer on the associated LinphoneCore + */ + LinphoneCore *getLinphoneCore() const; + /** + * @brief Check wehter the tunnel is connected + * @return True whether the tunnel is connected + */ + bool isConnected() const; + private: enum EventType{ UdpMirrorClientEvent, @@ -146,8 +155,6 @@ class UdpMirrorClient; }mData; }; typedef std::list UdpMirrorClientList; - virtual bool isStarted(); - void onIterate(); static int customSendto(struct _RtpTransport *t, mblk_t *msg , int flags, const struct sockaddr *to, socklen_t tolen); static int customRecvfrom(struct _RtpTransport *t, mblk_t *msg, int flags, struct sockaddr *from, socklen_t *fromlen); static int eXosipSendto(int fd,const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen,void* userdata); @@ -156,35 +163,41 @@ class UdpMirrorClient; static void tunnelCallback(bool connected, TunnelManager *zis); static void sOnIterate(TunnelManager *zis); static void sUdpMirrorClientCallback(bool result, void* data); + static void networkReachableCb(LinphoneCore *lc, bool_t reachable); + + private: + void onIterate(); + void registration(); void waitUnRegistration(); void processTunnelEvent(const Event &ev); void processUdpMirrorEvent(const Event &ev); void postEvent(const Event &ev); + void startClient(); + void stopClient(); + void autoDetect(); + + private: LinphoneCore* mCore; - LCSipTransports mRegularTransport; #ifndef USE_BELLESIP TunnelSocket *mSipSocket; eXosip_transport_hooks_t mExosipTransport; #endif - StateCallback mCallback; - void * mCallbackData; - bool mEnabled; + LinphoneTunnelMode mMode; std::queue mEvq; std::list mServerAddrs; UdpMirrorClientList mUdpMirrorClients; UdpMirrorClientList::iterator mCurrentUdpMirrorClient; TunnelClient* mTunnelClient; - void stopClient(); Mutex mMutex; - static Mutex sMutex; - bool mAutoDetectStarted; - bool mReady; + bool mIsConnected; LinphoneRtpTransportFactories mTransportFactories; std::string mHttpUserName; std::string mHttpPasswd; std::string mHttpProxyHost; int mHttpProxyPort; - LinphoneFirewallPolicy mPreviousFirewallPolicy; + bool mPreviousRegistrationEnabled; + bool mTunnelizeSipPackets; + LinphoneCoreVTable *mVTable; }; /** diff --git a/coreapi/address.c b/coreapi/address.c index ec37255c1..250026911 100644 --- a/coreapi/address.c +++ b/coreapi/address.c @@ -184,6 +184,7 @@ bool_t linphone_address_weak_equal(const LinphoneAddress *a1, const LinphoneAddr /** * Destroys a LinphoneAddress object (actually calls linphone_address_unref()). + * @deprecated Use linphone_address_unref() instead **/ void linphone_address_destroy(LinphoneAddress *u){ sal_address_unref(u); diff --git a/coreapi/authentication.c b/coreapi/authentication.c index d763f8902..de7248316 100644 --- a/coreapi/authentication.c +++ b/coreapi/authentication.c @@ -21,7 +21,7 @@ * 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 "private.h" #include "lpconfig.h" @@ -143,7 +143,7 @@ void linphone_auth_info_write_config(LpConfig *config, LinphoneAuthInfo *obj, in char key[50]; sprintf(key,"auth_info_%i",pos); lp_config_clean_section(config,key); - + if (obj==NULL || lp_config_get_int(config, "sip", "store_auth_info", 1) == 0){ return; } @@ -176,12 +176,12 @@ LinphoneAuthInfo *linphone_auth_info_new_from_config_file(LpConfig * config, int char key[50]; const char *username,*userid,*passwd,*ha1,*realm,*domain; LinphoneAuthInfo *ret; - + sprintf(key,"auth_info_%i",pos); if (!lp_config_has_section(config,key)){ return NULL; } - + username=lp_config_get_string(config,key,"username",NULL); userid=lp_config_get_string(config,key,"userid",NULL); passwd=lp_config_get_string(config,key,"passwd",NULL); @@ -221,7 +221,7 @@ static int realm_match(const char *realm1, const char *realm2){ static const LinphoneAuthInfo *find_auth_info(LinphoneCore *lc, const char *username, const char *realm, const char *domain){ MSList *elem; const LinphoneAuthInfo *ret=NULL; - + for (elem=lc->auth_info;elem!=NULL;elem=elem->next) { LinphoneAuthInfo *pinfo = (LinphoneAuthInfo*)elem->data; if (username && pinfo->username && strcmp(username,pinfo->username)==0) { @@ -240,7 +240,7 @@ static const LinphoneAuthInfo *find_auth_info(LinphoneCore *lc, const char *user } } else if (domain && pinfo->domain && strcmp(domain,pinfo->domain)==0) { return pinfo; - } else if (!domain) { + } else if (!domain) { return pinfo; } } @@ -249,7 +249,7 @@ static const LinphoneAuthInfo *find_auth_info(LinphoneCore *lc, const char *user } /** - * Find authentication info matching realm, username, domain criterias. + * Find authentication info matching realm, username, domain criteria. * First of all, (realm,username) pair are searched. If multiple results (which should not happen because realm are supposed to be unique), then domain is added to the search. * @param lc the LinphoneCore * @param realm the authentication 'realm' (optional) @@ -264,7 +264,7 @@ const LinphoneAuthInfo *linphone_core_find_auth_info(LinphoneCore *lc, const cha if (ai==NULL && domain){ ai=find_auth_info(lc,username,realm,domain); } - } + } if (ai == NULL && domain != NULL) { ai=find_auth_info(lc,username,NULL,domain); } @@ -292,8 +292,8 @@ LinphoneAuthInfo * linphone_core_create_auth_info(LinphoneCore *lc, const char * /** * Adds authentication information to the LinphoneCore. - * - * This information will be used during all SIP transacations that require authentication. + * + * This information will be used during all SIP transactions that require authentication. **/ void linphone_core_add_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *info){ LinphoneAuthInfo *ai; @@ -301,7 +301,7 @@ void linphone_core_add_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *info) MSList *l; int restarted_op_count=0; bool_t updating=FALSE; - + if (info->ha1==NULL && info->passwd==NULL){ ms_error("linphone_core_add_auth_info(): info supplied with empty password or ha1."); return; @@ -371,7 +371,6 @@ void linphone_core_remove_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *in r=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,info->realm,info->username,info->domain); if (r){ lc->auth_info=ms_list_remove(lc->auth_info,r); - /*printf("len=%i newlen=%i\n",len,newlen);*/ linphone_auth_info_destroy(r); write_auth_infos(lc); } @@ -379,6 +378,8 @@ void linphone_core_remove_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *in /** * Returns an unmodifiable list of currently entered LinphoneAuthInfo. + * @param[in] lc The LinphoneCore object + * @return \mslist{LinphoneAuthInfo} **/ const MSList *linphone_core_get_auth_info_list(const LinphoneCore *lc){ return lc->auth_info; diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index 9693226dd..6c2e84483 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -98,12 +98,16 @@ void sal_disable_logs() { void sal_add_pending_auth(Sal *sal, SalOp *op){ if (ms_list_find(sal->pending_auths,op)==NULL){ sal->pending_auths=ms_list_append(sal->pending_auths,op); + op->has_auth_pending=TRUE; } } void sal_remove_pending_auth(Sal *sal, SalOp *op){ - if (ms_list_find(sal->pending_auths,op)){ - sal->pending_auths=ms_list_remove(sal->pending_auths,op); + if (op->has_auth_pending){ + op->has_auth_pending=FALSE; + if (ms_list_find(sal->pending_auths,op)){ + sal->pending_auths=ms_list_remove(sal->pending_auths,op); + } } } @@ -137,7 +141,7 @@ void sal_process_authentication(SalOp *op) { return; } - if (belle_sip_provider_add_authorization(op->base.root->prov,new_request,response,from_uri,&auth_list)) { + if (belle_sip_provider_add_authorization(op->base.root->prov,new_request,response,from_uri,&auth_list,op->base.realm)) { if (is_within_dialog) { sal_op_send_request(op,new_request); } else { @@ -432,8 +436,8 @@ Sal * sal_init(){ sal->stack = belle_sip_stack_new(NULL); sal->user_agent=belle_sip_header_user_agent_new(); -#if defined(PACKAGE_NAME) && defined(LINPHONE_VERSION) - belle_sip_header_user_agent_add_product(sal->user_agent, PACKAGE_NAME "/" LINPHONE_VERSION); +#if defined(PACKAGE_NAME) && defined(LIBLINPHONE_VERSION) + belle_sip_header_user_agent_add_product(sal->user_agent, PACKAGE_NAME "/" LIBLINPHONE_VERSION); #endif sal_append_stack_string_to_user_agent(sal); belle_sip_object_ref(sal->user_agent); @@ -530,6 +534,8 @@ void sal_uninit(Sal* sal){ belle_sip_object_unref(sal->prov); belle_sip_object_unref(sal->stack); belle_sip_object_unref(sal->listener); + if (sal->supported) belle_sip_object_unref(sal->supported); + ms_list_free_with_data(sal->supported_tags,ms_free); if (sal->uuid) ms_free(sal->uuid); if (sal->root_ca) ms_free(sal->root_ca); ms_free(sal); @@ -555,7 +561,7 @@ int sal_add_listen_port(Sal *ctx, SalAddress* addr){ sal_address_get_port(addr), sal_transport_to_string(sal_address_get_transport(addr))); if (sal_address_get_port(addr)==-1 && lp==NULL){ - int random_port=(0xDFFF&random())+1024; + int random_port=(0xDFFF&ortp_random())+1024; ms_warning("This version of belle-sip doesn't support random port, choosing one here."); lp = belle_sip_stack_create_listening_point(ctx->stack, sal_address_get_domain(addr), @@ -639,28 +645,42 @@ void sal_set_keepalive_period(Sal *ctx,unsigned int value){ belle_sip_listening_point_set_keep_alive(lp,ctx->keep_alive); } } - return ; } int sal_enable_tunnel(Sal *ctx, void *tunnelclient) { #ifdef TUNNEL_ENABLED - belle_sip_listening_point_t *lp; - int result; - - sal_unlisten_ports(ctx); - lp = belle_sip_tunnel_listening_point_new(ctx->stack, tunnelclient); - if (lp == NULL) return -1; - - belle_sip_listening_point_set_keep_alive(lp, ctx->keep_alive); - result = belle_sip_provider_add_listening_point(ctx->prov, lp); - set_tls_properties(ctx); - return result; + belle_sip_listening_point_t *lp_udp = NULL; + if(ctx->lp_tunnel != NULL) { + ortp_error("sal_enable_tunnel(): tunnel is already enabled"); + return -1; + } + while((lp_udp = belle_sip_provider_get_listening_point(ctx->prov, "udp")) != NULL) { + belle_sip_object_ref(lp_udp); + belle_sip_provider_remove_listening_point(ctx->prov, lp_udp); + ctx->udp_listening_points = ms_list_append(ctx->udp_listening_points, lp_udp); + } + ctx->lp_tunnel = belle_sip_tunnel_listening_point_new(ctx->stack, tunnelclient); + if(ctx->lp_tunnel == NULL) return -1; + belle_sip_listening_point_set_keep_alive(ctx->lp_tunnel, ctx->keep_alive); + belle_sip_provider_add_listening_point(ctx->prov, ctx->lp_tunnel); + belle_sip_object_ref(ctx->lp_tunnel); + return 0; #else return 0; #endif } void sal_disable_tunnel(Sal *ctx) { #ifdef TUNNEL_ENABLED - sal_unlisten_ports(ctx); + MSList *it; + if(ctx->lp_tunnel) { + belle_sip_provider_remove_listening_point(ctx->prov, ctx->lp_tunnel); + belle_sip_object_unref(ctx->lp_tunnel); + ctx->lp_tunnel = NULL; + for(it=ctx->udp_listening_points; it!=NULL; it=it->next) { + belle_sip_provider_add_listening_point(ctx->prov, (belle_sip_listening_point_t *)it->data); + } + ms_list_free_with_data(ctx->udp_listening_points, belle_sip_object_unref); + ctx->udp_listening_points = NULL; + } #endif } /** @@ -928,10 +948,79 @@ int sal_create_uuid(Sal*ctx, char *uuid, size_t len){ return 0; } +static void make_supported_header(Sal *sal){ + MSList *it; + char *alltags=NULL; + size_t buflen=64; + size_t written=0; + + if (sal->supported){ + belle_sip_object_unref(sal->supported); + sal->supported=NULL; + } + for(it=sal->supported_tags;it!=NULL;it=it->next){ + const char *tag=(const char*)it->data; + size_t taglen=strlen(tag); + if (alltags==NULL || (written+taglen+1>=buflen)) alltags=ms_realloc(alltags,(buflen=buflen*2)); + snprintf(alltags+written,buflen-written,it->next ? "%s, " : "%s",tag); + } + if (alltags){ + sal->supported=belle_sip_header_create("Supported",alltags); + if (sal->supported){ + belle_sip_object_ref(sal->supported); + } + ms_free(alltags); + } +} + +void sal_set_supported_tags(Sal *ctx, const char* tags){ + ctx->supported_tags=ms_list_free_with_data(ctx->supported_tags,ms_free); + if (tags){ + char *iter; + char *buffer=ms_strdup(tags); + char *tag; + char *context=NULL; + iter=buffer; + while((tag=strtok_r(iter,", ",&context))!=NULL){ + iter=NULL; + ctx->supported_tags=ms_list_append(ctx->supported_tags,ms_strdup(tag)); + } + ms_free(buffer); + } + make_supported_header(ctx); +} + +const char *sal_get_supported_tags(Sal *ctx){ + if (ctx->supported){ + return belle_sip_header_get_unparsed_value(ctx->supported); + } + return NULL; +} + +void sal_add_supported_tag(Sal *ctx, const char* tag){ + MSList *elem=ms_list_find_custom(ctx->supported_tags,(MSCompareFunc)strcasecmp,tag); + if (!elem){ + ctx->supported_tags=ms_list_append(ctx->supported_tags,ms_strdup(tag)); + make_supported_header(ctx); + } + +} + +void sal_remove_supported_tag(Sal *ctx, const char* tag){ + MSList *elem=ms_list_find_custom(ctx->supported_tags,(MSCompareFunc)strcasecmp,tag); + if (elem){ + ms_free(elem->data); + ctx->supported_tags=ms_list_remove_link(ctx->supported_tags,elem); + make_supported_header(ctx); + } +} + + + belle_sip_response_t* sal_create_response_from_request ( Sal* sal, belle_sip_request_t* req, int code ) { belle_sip_response_t *resp=belle_sip_response_create_from_request(req,code); belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp),BELLE_SIP_HEADER(sal->user_agent)); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp),sal_make_supported_header(sal)); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp),sal->supported); return resp; } diff --git a/coreapi/bellesip_sal/sal_impl.h b/coreapi/bellesip_sal/sal_impl.h index a20150de2..07124feb3 100644 --- a/coreapi/bellesip_sal/sal_impl.h +++ b/coreapi/bellesip_sal/sal_impl.h @@ -33,12 +33,16 @@ struct Sal{ belle_sip_provider_t *prov; belle_sip_header_user_agent_t* user_agent; belle_sip_listener_t *listener; + belle_sip_listening_point_t *lp_tunnel; + MSList *udp_listening_points; void *up; /*user pointer*/ int session_expires; unsigned int keep_alive; char *root_ca; char *uuid; int refresher_retry_after; /*retry after value for refresher*/ + MSList *supported_tags;/*list of char * */ + belle_sip_header_t *supported; bool_t one_matching_codec; bool_t use_tcp_tls_keep_alive; bool_t nat_helper_enabled; @@ -102,6 +106,7 @@ struct SalOp{ bool_t sdp_offering; bool_t call_released; bool_t manual_refresher; + bool_t has_auth_pending; int auth_requests; /*number of auth requested for this op*/ }; @@ -164,8 +169,6 @@ bool_t sal_op_get_body(SalOp *op, belle_sip_message_t *msg, SalBody *salbody); SalReason sal_reason_to_sip_code(SalReason r); -belle_sip_header_t * sal_make_supported_header(Sal *sal); - void _sal_op_add_custom_headers(SalOp *op, belle_sip_message_t *msg); #endif /* SAL_IMPL_H_ */ diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c index 26bbdb038..7c9c8026c 100644 --- a/coreapi/bellesip_sal/sal_op_call.c +++ b/coreapi/bellesip_sal/sal_op_call.c @@ -185,6 +185,7 @@ static void call_process_response(void *op_base, const belle_sip_response_event_ int code = belle_sip_response_get_status_code(response); belle_sip_header_content_type_t *header_content_type=NULL; belle_sip_dialog_t *dialog=belle_sip_response_event_get_dialog(event); + const char *method; if (!client_transaction) { ms_warning("Discarding stateless response [%i] on op [%p]",code,op); @@ -193,13 +194,13 @@ static void call_process_response(void *op_base, const belle_sip_response_event_ req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction)); set_or_update_dialog(op,dialog); dialog_state=dialog ? belle_sip_dialog_get_state(dialog) : BELLE_SIP_DIALOG_NULL; - + method=belle_sip_request_get_method(req); ms_message("Op [%p] receiving call response [%i], dialog is [%p] in state [%s]",op,code,dialog,belle_sip_dialog_state_to_string(dialog_state)); switch(dialog_state) { case BELLE_SIP_DIALOG_NULL: case BELLE_SIP_DIALOG_EARLY: { - if (strcmp("INVITE",belle_sip_request_get_method(req))==0 ) { + if (strcmp("INVITE",method)==0 ) { if (op->state == SalOpStateTerminating) { /*check if CANCEL was sent before*/ if (strcmp("CANCEL",belle_sip_request_get_method(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_client_trans))))!=0) { @@ -238,28 +239,28 @@ static void call_process_response(void *op_base, const belle_sip_response_event_ case BELLE_SIP_DIALOG_CONFIRMED: { switch (op->state) { case SalOpStateEarly:/*invite case*/ - case SalOpStateActive: /*re-invite case*/ - if (code >=200 - && code<300 - && strcmp("INVITE",belle_sip_request_get_method(req))==0) { - handle_sdp_from_response(op,response); - ack=belle_sip_dialog_create_ack(op->dialog,belle_sip_dialog_get_local_seq_number(op->dialog)); - if (ack==NULL) { - ms_error("This call has been already terminated."); - return ; + case SalOpStateActive: /*re-invite, INFO, UPDATE case*/ + if (strcmp("INVITE",method)==0){ + if (code >=200 && code<300) { + handle_sdp_from_response(op,response); + ack=belle_sip_dialog_create_ack(op->dialog,belle_sip_dialog_get_local_seq_number(op->dialog)); + if (ack==NULL) { + ms_error("This call has been already terminated."); + return ; + } + if (op->sdp_answer){ + set_sdp(BELLE_SIP_MESSAGE(ack),op->sdp_answer); + belle_sip_object_unref(op->sdp_answer); + op->sdp_answer=NULL; + } + belle_sip_dialog_send_ack(op->dialog,ack); + op->base.root->callbacks.call_accepted(op); /*INVITE*/ + op->state=SalOpStateActive; + }else if (code >= 300){ + call_set_error(op,response); } - if (op->sdp_answer){ - set_sdp(BELLE_SIP_MESSAGE(ack),op->sdp_answer); - belle_sip_object_unref(op->sdp_answer); - op->sdp_answer=NULL; - } - belle_sip_dialog_send_ack(op->dialog,ack); - op->base.root->callbacks.call_accepted(op); /*INVITE*/ - op->state=SalOpStateActive; - } else if (code >= 300 && strcmp("INVITE",belle_sip_request_get_method(req))==0){ - call_set_error(op,response); - } else if (code == 491 - && strcmp("INFO",belle_sip_request_get_method(req)) == 0 + }else if (strcmp("INFO",method)==0){ + if (code == 491 && (header_content_type = belle_sip_message_get_header_by_type(req,belle_sip_header_content_type_t)) && strcmp("application",belle_sip_header_content_type_get_type(header_content_type))==0 && strcmp("media_control+xml",belle_sip_header_content_type_get_subtype(header_content_type))==0) { @@ -267,8 +268,11 @@ static void call_process_response(void *op_base, const belle_sip_response_event_ belle_sip_source_t *s=sal_create_timer(op->base.root,vfu_retry,sal_op_ref(op), retry_in, "vfu request retry"); ms_message("Rejected vfu request on op [%p], just retry in [%ui] ms",op,retry_in); belle_sip_object_unref(s); - }else { - /*ignoring*/ + }else { + /*ignoring*/ + } + }else if (strcmp("UPDATE",method)==0){ + op->base.root->callbacks.call_accepted(op); /*INVITE*/ } break; case SalOpStateTerminating: @@ -419,6 +423,7 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t belle_sip_response_t* resp; belle_sip_header_t* call_info; const char *method=belle_sip_request_get_method(req); + bool_t is_update=FALSE; if (strcmp("ACK",method)!=0){ /*ACK does'nt create srv transaction*/ server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,belle_sip_request_event_get_request(event)); @@ -490,7 +495,7 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t } else if (strcmp("UPDATE",method)==0) { sal_op_reset_descriptions(op); if (process_sdp_for_invite(op,req)==0) - op->base.root->callbacks.call_updating(op); + op->base.root->callbacks.call_updating(op,TRUE); } else { belle_sip_error("Unexpected method [%s] for dialog state BELLE_SIP_DIALOG_EARLY",belle_sip_request_get_method(req)); unsupported_method(server_transaction,req); @@ -522,11 +527,20 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t op->base.root->callbacks.call_terminated(op,op->dir==SalOpDirIncoming?sal_op_get_from(op):sal_op_get_to(op)); op->state=SalOpStateTerminating; /*call end not notified by dialog deletion because transaction can end before dialog*/ - } else if(strcmp("INVITE",method)==0) { - /*re-invite*/ - sal_op_reset_descriptions(op); - if (process_sdp_for_invite(op,req)==0) - op->base.root->callbacks.call_updating(op); + } else if(strcmp("INVITE",method)==0 || (is_update=(strcmp("UPDATE",method)==0)) ) { + if (is_update && !belle_sip_message_get_body(BELLE_SIP_MESSAGE(req))) { + /*session timer case*/ + /*session expire should be handled. to be done when real session timer (rfc4028) will be implemented*/ + resp=sal_op_create_response_from_request(op,req,200); + belle_sip_server_transaction_send_response(server_transaction,resp); + belle_sip_object_unref(op->pending_update_server_trans); + op->pending_update_server_trans=NULL; + } else { + /*re-invite*/ + sal_op_reset_descriptions(op); + if (process_sdp_for_invite(op,req)==0) + op->base.root->callbacks.call_updating(op,is_update); + } } else if (strcmp("INFO",method)==0){ if (belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)) && strstr(belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)),"picture_fast_update")) { @@ -564,22 +578,6 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t belle_sip_server_transaction_send_response(server_transaction,sal_op_create_response_from_request(op,req,481)); } else if (strcmp("MESSAGE",method)==0){ sal_process_incoming_message(op,event); - } else if (strcmp("UPDATE",method)==0) { - - /*FIXME jehan: It might be better to silently accept UPDATE which do not modify either the number or the nature of streams*/ - - /*rfc 3311 - * 5.2 Receiving an UPDATE - * ... - * If the UAS cannot change the session parameters without prompting the user, it SHOULD reject - * the request with a 504 response. - */ - resp=sal_op_create_response_from_request(op,req,504); - belle_sip_response_set_reason_phrase(resp,"Cannot change the session parameters without prompting the user"); - /*belle_sip_message_add_header( BELLE_SIP_MESSAGE(resp) - ,belle_sip_header_create( "Warning", "Cannot change the session parameters without prompting the user"));*/ - belle_sip_server_transaction_send_response(server_transaction,resp); - return; }else{ ms_error("unexpected method [%s] for dialog [%p]",belle_sip_request_get_method(req),op->dialog); unsupported_method(server_transaction,req); @@ -796,13 +794,15 @@ int sal_call_decline(SalOp *op, SalReason reason, const char *redirection /*opti return 0; } -int sal_call_update(SalOp *op, const char *subject){ - +int sal_call_update(SalOp *op, const char *subject, bool_t no_user_consent){ belle_sip_request_t *update; belle_sip_dialog_state_t state=belle_sip_dialog_get_state(op->dialog); /*check for dialog state*/ if ( state == BELLE_SIP_DIALOG_CONFIRMED) { - update=belle_sip_dialog_create_request(op->dialog,"INVITE"); + if (no_user_consent) + update=belle_sip_dialog_create_request(op->dialog,"UPDATE"); + else + update=belle_sip_dialog_create_request(op->dialog,"INVITE"); } else if (state == BELLE_SIP_DIALOG_EARLY) { update=belle_sip_dialog_create_request(op->dialog,"UPDATE"); } else { diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c index 649a4e240..ed18f52d0 100644 --- a/coreapi/bellesip_sal/sal_op_impl.c +++ b/coreapi/bellesip_sal/sal_op_impl.c @@ -118,9 +118,7 @@ belle_sip_header_contact_t* sal_op_create_contact(SalOp *op){ return contact_header; } -belle_sip_header_t * sal_make_supported_header(Sal *sal){ - return belle_sip_header_create("Supported","replaces, outbound"); -} + static void add_initial_route_set(belle_sip_request_t *request, const MSList *list){ const MSList *elem; @@ -137,7 +135,7 @@ static void add_initial_route_set(belle_sip_request_t *request, const MSList *li continue; } } - + route=belle_sip_header_route_create((belle_sip_header_address_t*)addr); uri=belle_sip_header_address_get_uri((belle_sip_header_address_t*)route); belle_sip_uri_set_lr_param(uri,1); @@ -180,11 +178,11 @@ belle_sip_request_t* sal_op_build_request(SalOp *op,const char* method) { belle_sip_header_p_preferred_identity_t* p_preferred_identity=belle_sip_header_p_preferred_identity_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_from_address(op))); belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(p_preferred_identity)); } - + if (elem && strcmp(method,"REGISTER")!=0 && !op->base.root->no_initial_route){ add_initial_route_set(req,elem); } - + if (strcmp("REGISTER",method)!=0 && op->privacy!=SalPrivacyNone ){ belle_sip_header_privacy_t* privacy_header=belle_sip_header_privacy_new(); if (op->privacy&SalPrivacyCritical) @@ -201,7 +199,7 @@ belle_sip_request_t* sal_op_build_request(SalOp *op,const char* method) { belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacyUser)); belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(privacy_header)); } - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),sal_make_supported_header(op->base.root)); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),op->base.root->supported); return req; } @@ -332,7 +330,7 @@ static int _sal_op_send_request_with_contact(SalOp* op, belle_sip_request_t* req if (!belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_AUTHORIZATION) && !belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_PROXY_AUTHORIZATION)) { /*hmm just in case we already have authentication param in cache*/ - belle_sip_provider_add_authorization(op->base.root->prov,request,NULL,NULL,NULL); + belle_sip_provider_add_authorization(op->base.root->prov,request,NULL,NULL,NULL,op->base.realm); } result = belle_sip_client_transaction_send_request_to(client_transaction,next_hop_uri/*might be null*/); @@ -608,7 +606,7 @@ int sal_op_send_and_create_refresher(SalOp* op,belle_sip_request_t* req, int exp belle_sip_object_unref(op->refresher); } if ((op->refresher = belle_sip_client_transaction_create_refresher(op->pending_client_trans))) { - /*since refresher acquires the transaction, we should remove our context from the transaction, because we won't be notified + /*since refresher acquires the transaction, we should remove our context from the transaction, because we won't be notified * that it is terminated anymore.*/ sal_op_unref(op);/*loose the reference that was given to the transaction when creating it*/ /* Note that the refresher will replace our data with belle_sip_transaction_set_application_data(). @@ -617,6 +615,7 @@ int sal_op_send_and_create_refresher(SalOp* op,belle_sip_request_t* req, int exp notify the user as a normal transaction*/ belle_sip_refresher_set_listener(op->refresher,listener,op); belle_sip_refresher_set_retry_after(op->refresher,op->base.root->refresher_retry_after); + belle_sip_refresher_set_realm(op->refresher,op->base.realm); belle_sip_refresher_enable_manual_mode(op->refresher,op->manual_refresher); return 0; } else { diff --git a/coreapi/bellesip_sal/sal_op_presence.c b/coreapi/bellesip_sal/sal_op_presence.c index e1ab054aa..23db49e6f 100644 --- a/coreapi/bellesip_sal/sal_op_presence.c +++ b/coreapi/bellesip_sal/sal_op_presence.c @@ -35,7 +35,7 @@ void sal_add_presence_info(SalOp *op, belle_sip_message_t *notify, SalPresenceMo belle_sip_message_remove_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_CONTENT_TYPE); belle_sip_message_remove_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_CONTENT_LENGTH); belle_sip_message_set_body(BELLE_SIP_MESSAGE(notify),NULL,0); - + if (content){ belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify) ,BELLE_SIP_HEADER(belle_sip_header_content_type_create("application","pidf+xml"))); @@ -95,7 +95,7 @@ static void presence_response_event(void *op_base, const belle_sip_response_even belle_sip_request_t* request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction)); int code = belle_sip_response_get_status_code(response); belle_sip_header_expires_t* expires; - + sal_op_set_error_info_from_response(op,response); if (code>=300) { @@ -127,6 +127,7 @@ static void presence_response_event(void *op_base, const belle_sip_response_even if (expires>0){ op->refresher=belle_sip_client_transaction_create_refresher(client_transaction); belle_sip_refresher_set_listener(op->refresher,presence_refresher_listener,op); + belle_sip_refresher_set_realm(op->refresher,op->base.realm); } } break; @@ -164,7 +165,7 @@ static SalPresenceModel * process_presence_notification(SalOp *op, belle_sip_req return NULL; if (belle_sip_header_content_length_get_content_length(content_length) == 0) return NULL; - + if (body==NULL) return NULL; op->base.root->callbacks.parse_presence_requested(op, @@ -181,7 +182,7 @@ static void handle_notify(SalOp *op, belle_sip_request_t *req){ belle_sip_server_transaction_t* server_transaction=op->pending_server_trans; belle_sip_header_subscription_state_t* subscription_state_header=belle_sip_message_get_header_by_type(req,belle_sip_header_subscription_state_t); SalSubscribeStatus sub_state; - + if (strcmp("NOTIFY",belle_sip_request_get_method(req))==0) { SalPresenceModel *presence_model = NULL; const char* body = belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)); @@ -194,7 +195,7 @@ static void handle_notify(SalOp *op, belle_sip_request_t *req){ presence_model = process_presence_notification(op, req); if (presence_model != NULL || body==NULL) { /* Presence notification body parsed successfully. */ - + resp = sal_op_create_response_from_request(op, req, 200); /*create first because the op may be destroyed by notify_presence */ op->base.root->callbacks.notify_presence(op, sub_state, presence_model, NULL); } else if (body){ @@ -214,7 +215,7 @@ static void presence_process_request_event(void *op_base, const belle_sip_reques belle_sip_header_expires_t* expires = belle_sip_message_get_header_by_type(req,belle_sip_header_expires_t); belle_sip_response_t* resp; const char *method=belle_sip_request_get_method(req); - + belle_sip_object_ref(server_transaction); if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans); op->pending_server_trans=server_transaction; @@ -256,7 +257,7 @@ static void presence_process_request_event(void *op_base, const belle_sip_reques } } break; - default: + default: ms_error("unexpected dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state)); break; } diff --git a/coreapi/call_log.c b/coreapi/call_log.c new file mode 100644 index 000000000..d1e59578f --- /dev/null +++ b/coreapi/call_log.c @@ -0,0 +1,299 @@ +/* +linphone +Copyright (C) 2010-2014 Belledonne Communications SARL + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#define _XOPEN_SOURCE 700 /*required for strptime of GNU libc*/ + +#include +#include "private.h" + + +/******************************************************************************* + * Internal functions * + ******************************************************************************/ + +/*prevent a gcc bug with %c*/ +static size_t my_strftime(char *s, size_t max, const char *fmt, const struct tm *tm){ + return strftime(s, max, fmt, tm); +} + +static time_t string_to_time(const char *date){ +#ifndef WIN32 + struct tm tmtime={0}; + strptime(date,"%c",&tmtime); + return mktime(&tmtime); +#else + return 0; +#endif +} + +static void set_call_log_date(LinphoneCallLog *cl, time_t start_time){ + struct tm loctime; +#ifdef WIN32 +#if !defined(_WIN32_WCE) + loctime=*localtime(&start_time); + /*FIXME*/ +#endif /*_WIN32_WCE*/ +#else + localtime_r(&start_time,&loctime); +#endif + my_strftime(cl->start_date,sizeof(cl->start_date),"%c",&loctime); +} + +/******************************************************************************* + * Private functions * + ******************************************************************************/ + +void call_logs_write_to_config_file(LinphoneCore *lc){ + MSList *elem; + char logsection[32]; + int i; + char *tmp; + LpConfig *cfg=lc->config; + + if (linphone_core_get_global_state (lc)==LinphoneGlobalStartup) return; + + for(i=0,elem=lc->call_logs;elem!=NULL;elem=elem->next,++i){ + LinphoneCallLog *cl=(LinphoneCallLog*)elem->data; + snprintf(logsection,sizeof(logsection),"call_log_%i",i); + lp_config_clean_section(cfg,logsection); + lp_config_set_int(cfg,logsection,"dir",cl->dir); + lp_config_set_int(cfg,logsection,"status",cl->status); + tmp=linphone_address_as_string(cl->from); + lp_config_set_string(cfg,logsection,"from",tmp); + ms_free(tmp); + tmp=linphone_address_as_string(cl->to); + lp_config_set_string(cfg,logsection,"to",tmp); + ms_free(tmp); + if (cl->start_date_time) + lp_config_set_int64(cfg,logsection,"start_date_time",(int64_t)cl->start_date_time); + else lp_config_set_string(cfg,logsection,"start_date",cl->start_date); + lp_config_set_int(cfg,logsection,"duration",cl->duration); + if (cl->refkey) lp_config_set_string(cfg,logsection,"refkey",cl->refkey); + lp_config_set_float(cfg,logsection,"quality",cl->quality); + lp_config_set_int(cfg,logsection,"video_enabled", cl->video_enabled); + lp_config_set_string(cfg,logsection,"call_id",cl->call_id); + } + for(;imax_call_logs;++i){ + snprintf(logsection,sizeof(logsection),"call_log_%i",i); + lp_config_clean_section(cfg,logsection); + } +} + +void call_logs_read_from_config_file(LinphoneCore *lc){ + char logsection[32]; + int i; + const char *tmp; + uint64_t sec; + LpConfig *cfg=lc->config; + for(i=0;;++i){ + snprintf(logsection,sizeof(logsection),"call_log_%i",i); + if (lp_config_has_section(cfg,logsection)){ + LinphoneCallLog *cl; + LinphoneAddress *from=NULL,*to=NULL; + tmp=lp_config_get_string(cfg,logsection,"from",NULL); + if (tmp) from=linphone_address_new(tmp); + tmp=lp_config_get_string(cfg,logsection,"to",NULL); + if (tmp) to=linphone_address_new(tmp); + if (!from || !to) + continue; + cl=linphone_call_log_new(lp_config_get_int(cfg,logsection,"dir",0),from,to); + cl->status=lp_config_get_int(cfg,logsection,"status",0); + sec=lp_config_get_int64(cfg,logsection,"start_date_time",0); + if (sec) { + /*new call log format with date expressed in seconds */ + cl->start_date_time=(time_t)sec; + set_call_log_date(cl,cl->start_date_time); + }else{ + tmp=lp_config_get_string(cfg,logsection,"start_date",NULL); + if (tmp) { + strncpy(cl->start_date,tmp,sizeof(cl->start_date)); + cl->start_date_time=string_to_time(cl->start_date); + } + } + cl->duration=lp_config_get_int(cfg,logsection,"duration",0); + tmp=lp_config_get_string(cfg,logsection,"refkey",NULL); + if (tmp) cl->refkey=ms_strdup(tmp); + cl->quality=lp_config_get_float(cfg,logsection,"quality",-1); + cl->video_enabled=lp_config_get_int(cfg,logsection,"video_enabled",0); + tmp=lp_config_get_string(cfg,logsection,"call_id",NULL); + if (tmp) cl->call_id=ms_strdup(tmp); + lc->call_logs=ms_list_append(lc->call_logs,cl); + }else break; + } +} + + +/******************************************************************************* + * Public functions * + ******************************************************************************/ + +const char *linphone_call_log_get_call_id(const LinphoneCallLog *cl){ + return cl->call_id; +} + +LinphoneCallDir linphone_call_log_get_dir(LinphoneCallLog *cl){ + return cl->dir; +} + +int linphone_call_log_get_duration(LinphoneCallLog *cl){ + return cl->duration; +} + +LinphoneAddress *linphone_call_log_get_from_address(LinphoneCallLog *cl){ + return cl->from; +} + +const rtp_stats_t *linphone_call_log_get_local_stats(const LinphoneCallLog *cl){ + return &cl->local_stats; +} + +float linphone_call_log_get_quality(LinphoneCallLog *cl){ + return cl->quality; +} + +const char *linphone_call_log_get_ref_key(const LinphoneCallLog *cl){ + return cl->refkey; +} + +LinphoneAddress *linphone_call_log_get_remote_address(LinphoneCallLog *cl){ + return (cl->dir == LinphoneCallIncoming) ? cl->from : cl->to; +} + +const rtp_stats_t *linphone_call_log_get_remote_stats(const LinphoneCallLog *cl){ + return &cl->remote_stats; +} + +time_t linphone_call_log_get_start_date(LinphoneCallLog *cl){ + return cl->start_date_time; +} + +LinphoneCallStatus linphone_call_log_get_status(LinphoneCallLog *cl){ + return cl->status; +} + +LinphoneAddress *linphone_call_log_get_to_address(LinphoneCallLog *cl){ + return cl->to; +} + +void linphone_call_log_set_ref_key(LinphoneCallLog *cl, const char *refkey){ + if (cl->refkey!=NULL){ + ms_free(cl->refkey); + cl->refkey=NULL; + } + if (refkey) cl->refkey=ms_strdup(refkey); +} + +char * linphone_call_log_to_str(LinphoneCallLog *cl){ + char *status; + char *tmp; + char *from=linphone_address_as_string (cl->from); + char *to=linphone_address_as_string (cl->to); + switch(cl->status){ + case LinphoneCallAborted: + status=_("aborted"); + break; + case LinphoneCallSuccess: + status=_("completed"); + break; + case LinphoneCallMissed: + status=_("missed"); + break; + default: + status="unknown"; + } + tmp=ortp_strdup_printf(_("%s at %s\nFrom: %s\nTo: %s\nStatus: %s\nDuration: %i mn %i sec\n"), + (cl->dir==LinphoneCallIncoming) ? _("Incoming call") : _("Outgoing call"), + cl->start_date, + from, + to, + status, + cl->duration/60, + cl->duration%60); + ms_free(from); + ms_free(to); + return tmp; +} + +bool_t linphone_call_log_video_enabled(LinphoneCallLog *cl) { + return cl->video_enabled; +} + + +/******************************************************************************* + * Reference and user data handling functions * + ******************************************************************************/ + +void *linphone_call_log_get_user_data(const LinphoneCallLog *cl) { + return cl->user_data; +} + +void linphone_call_log_set_user_data(LinphoneCallLog *cl, void *ud) { + cl->user_data = ud; +} + +LinphoneCallLog * linphone_call_log_ref(LinphoneCallLog *cl) { + belle_sip_object_ref(cl); + return cl; +} + +void linphone_call_log_unref(LinphoneCallLog *cl) { + belle_sip_object_unref(cl); +} + +/******************************************************************************* + * Constructor and destructor functions * + ******************************************************************************/ + +static void _linphone_call_log_destroy(LinphoneCallLog *cl){ + if (cl->from!=NULL) linphone_address_destroy(cl->from); + if (cl->to!=NULL) linphone_address_destroy(cl->to); + if (cl->refkey!=NULL) ms_free(cl->refkey); + if (cl->call_id) ms_free(cl->call_id); + if (cl->reporting.reports[LINPHONE_CALL_STATS_AUDIO]!=NULL) linphone_reporting_destroy(cl->reporting.reports[LINPHONE_CALL_STATS_AUDIO]); + if (cl->reporting.reports[LINPHONE_CALL_STATS_VIDEO]!=NULL) linphone_reporting_destroy(cl->reporting.reports[LINPHONE_CALL_STATS_VIDEO]); +} + +LinphoneCallLog * linphone_call_log_new(LinphoneCallDir dir, LinphoneAddress *from, LinphoneAddress *to){ + LinphoneCallLog *cl=belle_sip_object_new(LinphoneCallLog); + cl->dir=dir; + cl->start_date_time=time(NULL); + set_call_log_date(cl,cl->start_date_time); + cl->from=from; + cl->to=to; + cl->status=LinphoneCallAborted; /*default status*/ + cl->quality=-1; + + cl->reporting.reports[LINPHONE_CALL_STATS_AUDIO]=linphone_reporting_new(); + cl->reporting.reports[LINPHONE_CALL_STATS_VIDEO]=linphone_reporting_new(); + return cl; +} + +/* DEPRECATED */ +void linphone_call_log_destroy(LinphoneCallLog *cl) { + belle_sip_object_unref(cl); +} + +BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneCallLog); + +BELLE_SIP_INSTANCIATE_VPTR(LinphoneCallLog, belle_sip_object_t, + (belle_sip_object_destroy_t)_linphone_call_log_destroy, + NULL, // clone + NULL, // marshal + FALSE +); diff --git a/coreapi/call_log.h b/coreapi/call_log.h new file mode 100644 index 000000000..d274037d2 --- /dev/null +++ b/coreapi/call_log.h @@ -0,0 +1,244 @@ +/* +linphone +Copyright (C) 2010-2014 Belledonne Communications SARL + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + + +#ifndef __LINPHONE_CALL_LOG_H__ +#define __LINPHONE_CALL_LOG_H__ + +/** + * @addtogroup call_logs + * @{ +**/ + + +/******************************************************************************* + * Structures and enums * + ******************************************************************************/ + +/** + * Enum representing the direction of a call. +**/ +enum _LinphoneCallDir { + LinphoneCallOutgoing, /**< outgoing calls*/ + LinphoneCallIncoming /**< incoming calls*/ +}; + +/** + * Typedef for enum +**/ +typedef enum _LinphoneCallDir LinphoneCallDir; + +/** + * Enum representing the status of a call +**/ +typedef enum _LinphoneCallStatus { + LinphoneCallSuccess, /**< The call was sucessful */ + LinphoneCallAborted, /**< The call was aborted */ + LinphoneCallMissed, /**< The call was missed (unanswered) */ + LinphoneCallDeclined /**< The call was declined, either locally or by remote end */ +} LinphoneCallStatus; + +/** + * Structure representing a call log. +**/ +typedef struct _LinphoneCallLog LinphoneCallLog; + + +/******************************************************************************* + * Public functions * + ******************************************************************************/ + +/** + * Get the call ID used by the call. + * @param[in] cl LinphoneCallLog object + * @return The call ID used by the call as a string. +**/ +LINPHONE_PUBLIC const char * linphone_call_log_get_call_id(const LinphoneCallLog *cl); + +/** + * Get the direction of the call. + * @param[in] cl LinphoneCallLog object + * @return The direction of the call. +**/ +LINPHONE_PUBLIC LinphoneCallDir linphone_call_log_get_dir(LinphoneCallLog *cl); + +/** + * Get the duration of the call. + * @param[in] cl LinphoneCallLog object + * @return The duration of the call in seconds. +**/ +LINPHONE_PUBLIC int linphone_call_log_get_duration(LinphoneCallLog *cl); + +/** + * Get the origin address (ie from) of the call. + * @param[in] cl LinphoneCallLog object + * @return The origin address (ie from) of the call. +**/ +LINPHONE_PUBLIC LinphoneAddress * linphone_call_log_get_from_address(LinphoneCallLog *cl); + +/** + * Get the RTP statistics computed locally regarding the call. + * @param[in] cl LinphoneCallLog object + * @return The RTP statistics that have been computed locally for the call. +**/ +LINPHONE_PUBLIC const rtp_stats_t * linphone_call_log_get_local_stats(const LinphoneCallLog *cl); + +/** + * Get the overall quality indication of the call. + * @param[in] cl LinphoneCallLog object + * @return The overall quality indication of the call. +**/ +LINPHONE_PUBLIC float linphone_call_log_get_quality(LinphoneCallLog *cl); + +/** + * Get the persistent reference key associated to the call log. + * + * The reference key can be for example an id to an external database. + * It is stored in the config file, thus can survive to process exits/restarts. + * + * @param[in] cl LinphoneCallLog object + * @return The reference key string that has been associated to the call log, or NULL if none has been associated. +**/ +LINPHONE_PUBLIC const char * linphone_call_log_get_ref_key(const LinphoneCallLog *cl); + +/** + * Get the remote address (that is from or to depending on call direction). + * @param[in] cl LinphoneCallLog object + * @return The remote address of the call. +**/ +LINPHONE_PUBLIC LinphoneAddress * linphone_call_log_get_remote_address(LinphoneCallLog *cl); + +/** + * Get the RTP statistics computed by the remote end and sent back via RTCP. + * @note Not implemented yet. + * @param[in] cl LinphoneCallLog object + * @return The RTP statistics that have been computed by the remote end for the call. +**/ +LINPHONE_PUBLIC const rtp_stats_t * linphone_call_log_get_remote_stats(const LinphoneCallLog *cl); + +/** + * Get the start date of the call. + * @param[in] cl LinphoneCallLog object + * @return The date of the beginning of the call. +**/ +LINPHONE_PUBLIC time_t linphone_call_log_get_start_date(LinphoneCallLog *cl); + +/** + * Get the status of the call. + * @param[in] cl LinphoneCallLog object + * @return The status of the call. +**/ +LINPHONE_PUBLIC LinphoneCallStatus linphone_call_log_get_status(LinphoneCallLog *cl); + +/** + * Get the destination address (ie to) of the call. + * @param[in] cl LinphoneCallLog object + * @return The destination address (ie to) of the call. +**/ +LINPHONE_PUBLIC LinphoneAddress * linphone_call_log_get_to_address(LinphoneCallLog *cl); + +/** + * Associate a persistent reference key to the call log. + * + * The reference key can be for example an id to an external database. + * It is stored in the config file, thus can survive to process exits/restarts. + * + * @param[in] cl LinphoneCallLog object + * @param[in] refkey The reference key string to associate to the call log. +**/ +LINPHONE_PUBLIC void linphone_call_log_set_ref_key(LinphoneCallLog *cl, const char *refkey); + +/** + * Tell whether video was enabled at the end of the call or not. + * @param[in] cl LinphoneCallLog object + * @return A boolean value telling whether video was enabled at the end of the call. +**/ +LINPHONE_PUBLIC bool_t linphone_call_log_video_enabled(LinphoneCallLog *cl); + +/** + * Get a human readable string describing the call. + * @note: the returned string must be freed by the application (use ms_free()). + * @param[in] cl LinphoneCallLog object + * @return A human readable string describing the call. +**/ +LINPHONE_PUBLIC char * linphone_call_log_to_str(LinphoneCallLog *cl); + + +/******************************************************************************* + * Reference and user data handling functions * + ******************************************************************************/ + +/** + * Get the user data associated with the call log. + * @param[in] cl LinphoneCallLog object + * @return The user data associated with the call log. +**/ +LINPHONE_PUBLIC void *linphone_call_log_get_user_data(const LinphoneCallLog *cl); + +/** + * Assign a user data to the call log. + * @param[in] cl LinphoneCallLog object + * @param[in] ud The user data to associate with the call log. +**/ +LINPHONE_PUBLIC void linphone_call_log_set_user_data(LinphoneCallLog *cl, void *ud); + +/** + * Acquire a reference to the call log. + * @param[in] cl LinphoneCallLog object + * @return The same LinphoneCallLog object +**/ +LINPHONE_PUBLIC LinphoneCallLog * linphone_call_log_ref(LinphoneCallLog *cl); + +/** + * Release a reference to the call log. + * @param[in] cl LinphoneCallLog object +**/ +LINPHONE_PUBLIC void linphone_call_log_unref(LinphoneCallLog *cl); + + +/******************************************************************************* + * DEPRECATED * + ******************************************************************************/ + +/** @deprecated Use linphone_call_log_get_from_address() instead. */ +#define linphone_call_log_get_from(cl) linphone_call_log_get_from_address(cl) + +/** @deprecated Use linphone_call_log_get_to_address() instead. */ +#define linphone_call_log_get_to(cl) linphone_call_log_get_to_address(cl) + +/** @deprecated Use linphone_call_log_set_user_data() instead. */ +#define linphone_call_log_set_user_pointer(cl, ud) linphone_call_log_set_user_data(cl, ud) + +/** @deprecated Use linphone_call_log_get_user_data() instead. */ +#define linphone_call_log_get_user_pointer(cl) linphone_call_log_get_user_data(cl) + +/** + * Destroy a LinphoneCallLog. + * @param cl LinphoneCallLog object + * @deprecated Use linphone_call_log_unref() instead. + */ +LINPHONE_PUBLIC void linphone_call_log_destroy(LinphoneCallLog *cl); + + +/** + * @} +**/ + + +#endif /* __LINPHONE_CALL_LOG_H__ */ diff --git a/coreapi/call_params.c b/coreapi/call_params.c new file mode 100644 index 000000000..a48066169 --- /dev/null +++ b/coreapi/call_params.c @@ -0,0 +1,207 @@ +/* +linphone +Copyright (C) 2010-2014 Belledonne Communications SARL + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "private.h" + + +/******************************************************************************* + * Internal functions * + ******************************************************************************/ + +SalMediaProto get_proto_from_call_params(const LinphoneCallParams *params) { + if ((params->media_encryption == LinphoneMediaEncryptionSRTP) && params->avpf_enabled) return SalProtoRtpSavpf; + if (params->media_encryption == LinphoneMediaEncryptionSRTP) return SalProtoRtpSavp; + if (params->avpf_enabled) return SalProtoRtpAvpf; + return SalProtoRtpAvp; +} + + +/******************************************************************************* + * Public functions * + ******************************************************************************/ + +void linphone_call_params_add_custom_header(LinphoneCallParams *params, const char *header_name, const char *header_value){ + params->custom_headers=sal_custom_header_append(params->custom_headers,header_name,header_value); +} + +LinphoneCallParams * linphone_call_params_copy(const LinphoneCallParams *cp){ + LinphoneCallParams *ncp=linphone_call_params_new(); + memcpy(ncp,cp,sizeof(LinphoneCallParams)); + if (cp->record_file) ncp->record_file=ms_strdup(cp->record_file); + if (cp->session_name) ncp->session_name=ms_strdup(cp->session_name); + /* + * The management of the custom headers is not optimal. We copy everything while ref counting would be more efficient. + */ + if (cp->custom_headers) ncp->custom_headers=sal_custom_header_clone(cp->custom_headers); + return ncp; +} + +bool_t linphone_call_params_early_media_sending_enabled(const LinphoneCallParams *cp){ + return cp->real_early_media; +} + +void linphone_call_params_enable_early_media_sending(LinphoneCallParams *cp, bool_t enabled){ + cp->real_early_media=enabled; +} + +void linphone_call_params_enable_low_bandwidth(LinphoneCallParams *cp, bool_t enabled){ + cp->low_bandwidth=enabled; +} + +void linphone_call_params_enable_video(LinphoneCallParams *cp, bool_t enabled){ + cp->has_video=enabled; +} + +const char *linphone_call_params_get_custom_header(const LinphoneCallParams *params, const char *header_name){ + return sal_custom_header_find(params->custom_headers,header_name); +} + +bool_t linphone_call_params_get_local_conference_mode(const LinphoneCallParams *cp){ + return cp->in_conference; +} + +LinphoneMediaEncryption linphone_call_params_get_media_encryption(const LinphoneCallParams *cp) { + return cp->media_encryption; +} + +LinphonePrivacyMask linphone_call_params_get_privacy(const LinphoneCallParams *params) { + return params->privacy; +} + +float linphone_call_params_get_received_framerate(const LinphoneCallParams *cp){ + return cp->received_fps; +} + +MSVideoSize linphone_call_params_get_received_video_size(const LinphoneCallParams *cp) { + return cp->recv_vsize; +} + +const char *linphone_call_params_get_record_file(const LinphoneCallParams *cp){ + return cp->record_file; +} + +const char * linphone_call_params_get_rtp_profile(const LinphoneCallParams *cp) { + return sal_media_proto_to_string(get_proto_from_call_params(cp)); +} + +float linphone_call_params_get_sent_framerate(const LinphoneCallParams *cp){ + return cp->sent_fps; +} + +MSVideoSize linphone_call_params_get_sent_video_size(const LinphoneCallParams *cp) { + return cp->sent_vsize; +} + +const char *linphone_call_params_get_session_name(const LinphoneCallParams *cp){ + return cp->session_name; +} + +const LinphonePayloadType* linphone_call_params_get_used_audio_codec(const LinphoneCallParams *cp) { + return cp->audio_codec; +} + +const LinphonePayloadType* linphone_call_params_get_used_video_codec(const LinphoneCallParams *cp) { + return cp->video_codec; +} + +bool_t linphone_call_params_low_bandwidth_enabled(const LinphoneCallParams *cp) { + return cp->low_bandwidth; +} + +void linphone_call_params_set_audio_bandwidth_limit(LinphoneCallParams *cp, int bandwidth){ + cp->audio_bw=bandwidth; +} + +void linphone_call_params_set_media_encryption(LinphoneCallParams *cp, LinphoneMediaEncryption e) { + cp->media_encryption = e; +} + +void linphone_call_params_set_privacy(LinphoneCallParams *params, LinphonePrivacyMask privacy) { + params->privacy=privacy; +} + +void linphone_call_params_set_record_file(LinphoneCallParams *cp, const char *path){ + if (cp->record_file){ + ms_free(cp->record_file); + cp->record_file=NULL; + } + if (path) cp->record_file=ms_strdup(path); +} + +void linphone_call_params_set_session_name(LinphoneCallParams *cp, const char *name){ + if (cp->session_name){ + ms_free(cp->session_name); + cp->session_name=NULL; + } + if (name) cp->session_name=ms_strdup(name); +} + +bool_t linphone_call_params_video_enabled(const LinphoneCallParams *cp){ + return cp->has_video; +} + + + +/******************************************************************************* + * Reference and user data handling functions * + ******************************************************************************/ + +void *linphone_call_params_get_user_data(const LinphoneCallParams *cp) { + return cp->user_data; +} + +void linphone_call_params_set_user_data(LinphoneCallParams *cp, void *ud) { + cp->user_data = ud; +} + +LinphoneCallParams * linphone_call_params_ref(LinphoneCallParams *cp) { + belle_sip_object_ref(cp); + return cp; +} + +void linphone_call_params_unref(LinphoneCallParams *cp) { + belle_sip_object_unref(cp); +} + +/******************************************************************************* + * Constructor and destructor functions * + ******************************************************************************/ + +static void _linphone_call_params_destroy(LinphoneCallParams *cp){ + if (cp->record_file) ms_free(cp->record_file); + if (cp->custom_headers) sal_custom_header_free(cp->custom_headers); +} + +LinphoneCallParams * linphone_call_params_new(void) { + return belle_sip_object_new(LinphoneCallParams); +} + +/* DEPRECATED */ +void linphone_call_params_destroy(LinphoneCallParams *cp) { + linphone_call_params_unref(cp); +} + +BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneCallParams); + +BELLE_SIP_INSTANCIATE_VPTR(LinphoneCallParams, belle_sip_object_t, + (belle_sip_object_destroy_t)_linphone_call_params_destroy, + NULL, // clone + NULL, // marshal + FALSE +); diff --git a/coreapi/call_params.h b/coreapi/call_params.h new file mode 100644 index 000000000..9c942826b --- /dev/null +++ b/coreapi/call_params.h @@ -0,0 +1,303 @@ +/* +linphone +Copyright (C) 2010-2014 Belledonne Communications SARL + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + + +#ifndef __LINPHONE_CALL_PARAMS_H__ +#define __LINPHONE_CALL_PARAMS_H__ + +/** + * @addtogroup call_control + * @{ +**/ + + +/******************************************************************************* + * Structures and enums * + ******************************************************************************/ + +/** + * Private structure definition for LinphoneCallParams. +**/ +struct _LinphoneCallParams; + +/** + * The LinphoneCallParams is an object containing various call related parameters. + * It can be used to retrieve parameters from a currently running call or modify + * the call's characteristics dynamically. +**/ +typedef struct _LinphoneCallParams LinphoneCallParams; + + +/******************************************************************************* + * Public functions * + ******************************************************************************/ + +/** + * Add a custom SIP header in the INVITE for a call. + * @param[in] cp The #LinphoneCallParams to add a custom SIP header to. + * @param[in] header_name The name of the header to add. + * @param[in] header_value The content of the header to add. +**/ +LINPHONE_PUBLIC void linphone_call_params_add_custom_header(LinphoneCallParams *cp, const char *header_name, const char *header_value); + +/** + * Copy an existing LinphoneCallParams object to a new LinphoneCallParams object. + * @param[in] cp The LinphoneCallParams object to copy. + * @return A copy of the LinphoneCallParams object. +**/ +LINPHONE_PUBLIC LinphoneCallParams * linphone_call_params_copy(const LinphoneCallParams *cp); + +/** + * Indicate whether sending of early media was enabled. + * @param[in] cp LinphoneCallParams object + * @return A boolean value telling whether sending of early media was enabled. +**/ +LINPHONE_PUBLIC bool_t linphone_call_params_early_media_sending_enabled(const LinphoneCallParams *cp); + +/** + * Enable sending of real early media (during outgoing calls). + * @param[in] cp LinphoneCallParams object + * @param[in] enabled A boolean value telling whether to enable early media sending or not. +**/ +LINPHONE_PUBLIC void linphone_call_params_enable_early_media_sending(LinphoneCallParams *cp, bool_t enabled); + +/** + * Indicate low bandwith mode. + * Configuring a call to low bandwidth mode will result in the core to activate several settings for the call in order to ensure that bitrate usage + * is lowered to the minimum possible. Typically, ptime (packetization time) will be increased, audio codec's output bitrate will be targetted to 20kbit/s provided + * that it is achievable by the codec selected after SDP handshake. Video is automatically disabled. + * @param[in] cp LinphoneCallParams object + * @param[in] enabled A boolean value telling whether to activate the low bandwidth mode or not. +**/ +LINPHONE_PUBLIC void linphone_call_params_enable_low_bandwidth(LinphoneCallParams *cp, bool_t enabled); + +/** + * Enable video stream. + * @param[in] cp LinphoneCallParams object + * @param[in] enabled A boolean value telling whether to enable video or not. +**/ +LINPHONE_PUBLIC void linphone_call_params_enable_video(LinphoneCallParams *cp, bool_t enabled); + +/** + * Get a custom SIP header. + * @param[in] cp The #LinphoneCallParams to get the custom SIP header from. + * @param[in] header_name The name of the header to get. + * @return The content of the header or NULL if not found. +**/ +LINPHONE_PUBLIC const char *linphone_call_params_get_custom_header(const LinphoneCallParams *cp, const char *header_name); + +/** + * Tell whether the call is part of the locally managed conference. + * @param[in] cp LinphoneCallParams object + * @return A boolean value telling whether the call is part of the locally managed conference. +**/ +LINPHONE_PUBLIC bool_t linphone_call_params_get_local_conference_mode(const LinphoneCallParams *cp); + +/** + * Get the kind of media encryption selected for the call. + * @param[in] cp LinphoneCallParams object + * @return The kind of media encryption selected for the call. +**/ +LINPHONE_PUBLIC LinphoneMediaEncryption linphone_call_params_get_media_encryption(const LinphoneCallParams *cp); + +/** + * Get requested level of privacy for the call. + * @param[in] cp LinphoneCallParams object + * @return The privacy mode used for the call. +**/ +LINPHONE_PUBLIC LinphonePrivacyMask linphone_call_params_get_privacy(const LinphoneCallParams *cp); + +/** + * Get the framerate of the video that is received. + * @param[in] cp LinphoneCallParams object + * @return The actual received framerate in frames per seconds, 0 if not available. + */ +LINPHONE_PUBLIC float linphone_call_params_get_received_framerate(const LinphoneCallParams *cp); + +/** + * Get the size of the video that is received. + * @param[in] cp LinphoneCallParams object + * @return The received video size or MS_VIDEO_SIZE_UNKNOWN if not available. + */ +LINPHONE_PUBLIC MSVideoSize linphone_call_params_get_received_video_size(const LinphoneCallParams *cp); + +/** + * Get the path for the audio recording of the call. + * @param[in] cp LinphoneCallParams object + * @return The path to the audio recording of the call. +**/ +LINPHONE_PUBLIC const char *linphone_call_params_get_record_file(const LinphoneCallParams *cp); + +/** + * Get the RTP profile being used. + * @param[in] cp #LinphoneCallParams object + * @return The RTP profile. + */ +LINPHONE_PUBLIC const char * linphone_call_params_get_rtp_profile(const LinphoneCallParams *cp); + +/** + * Get the framerate of the video that is sent. + * @param[in] cp LinphoneCallParams object + * @return The actual sent framerate in frames per seconds, 0 if not available. + */ +LINPHONE_PUBLIC float linphone_call_params_get_sent_framerate(const LinphoneCallParams *cp); + +/** + * Gets the size of the video that is sent. + * @param[in] cp LinphoneCalParams object + * @return The sent video size or MS_VIDEO_SIZE_UNKNOWN if not available. + */ +LINPHONE_PUBLIC MSVideoSize linphone_call_params_get_sent_video_size(const LinphoneCallParams *cp); + +/** + * Get the session name of the media session (ie in SDP). + * Subject from the SIP message can be retrieved using linphone_call_params_get_custom_header() and is different. + * @param[in] cp LinphoneCallParams object + * @return The session name of the media session. +**/ +LINPHONE_PUBLIC const char *linphone_call_params_get_session_name(const LinphoneCallParams *cp); + +/** + * Get the audio codec used in the call, described as a LinphonePayloadType object. + * @param[in] cp LinphoneCallParams object + * @return The LinphonePayloadType object corresponding to the audio codec being used in the call. +**/ +LINPHONE_PUBLIC const LinphonePayloadType* linphone_call_params_get_used_audio_codec(const LinphoneCallParams *cp); + +/** + * Get the video codec used in the call, described as a LinphonePayloadType structure. + * @param[in] cp LinphoneCallParams object + * @return The LinphonePayloadType object corresponding to the video codec being used in the call. +**/ +LINPHONE_PUBLIC const LinphonePayloadType* linphone_call_params_get_used_video_codec(const LinphoneCallParams *cp); + +/** + * Tell whether the call has been configured in low bandwidth mode or not. + * This mode can be automatically discovered thanks to a stun server when activate_edge_workarounds=1 in section [net] of configuration file. + * An application that would have reliable way to know network capacity may not use activate_edge_workarounds=1 but instead manually configure + * low bandwidth mode with linphone_call_params_enable_low_bandwidth(). + * When enabled, this param may transform a call request with video in audio only mode. + * @param[in] cp LinphoneCallParams object + * @return A boolean value telling whether the low bandwidth mode has been configured/detected. + */ +LINPHONE_PUBLIC bool_t linphone_call_params_low_bandwidth_enabled(const LinphoneCallParams *cp); + +/** + * Refine bandwidth settings for this call by setting a bandwidth limit for audio streams. + * As a consequence, codecs whose bitrates are not compatible with this limit won't be used. + * @param[in] cp LinphoneCallParams object + * @param[in] bw The audio bandwidth limit to set in kbit/s. +**/ +LINPHONE_PUBLIC void linphone_call_params_set_audio_bandwidth_limit(LinphoneCallParams *cp, int bw); + +/** + * Set requested media encryption for a call. + * @param[in] cp LinphoneCallParams object + * @param[in] enc The media encryption to use for the call. +**/ +LINPHONE_PUBLIC void linphone_call_params_set_media_encryption(LinphoneCallParams *cp, LinphoneMediaEncryption enc); + +/** + * Set requested level of privacy for the call. + * \xmlonly javascript \endxmlonly + * @param[in] cp LinphoneCallParams object + * @param[in] privacy The privacy mode to used for the call. +**/ +LINPHONE_PUBLIC void linphone_call_params_set_privacy(LinphoneCallParams *params, LinphonePrivacyMask privacy); + +/** + * Enable recording of the call. + * This function must be used before the call parameters are assigned to the call. + * The call recording can be started and paused after the call is established with + * linphone_call_start_recording() and linphone_call_pause_recording(). + * @param[in] cp LinphoneCallParams object + * @param[in] path A string containing the path and filename of the file where audio/video streams are to be written. + * The filename must have either .mkv or .wav extention. The video stream will be written only if a MKV file is given. +**/ +LINPHONE_PUBLIC void linphone_call_params_set_record_file(LinphoneCallParams *cp, const char *path); + +/** + * Set the session name of the media session (ie in SDP). + * Subject from the SIP message (which is different) can be set using linphone_call_params_set_custom_header(). + * @param[in] cp LinphoneCallParams object + * @param[in] name The session name to be used. +**/ +LINPHONE_PUBLIC void linphone_call_params_set_session_name(LinphoneCallParams *cp, const char *name); + +/** + * Tell whether video is enabled or not. + * @param[in] cp LinphoneCallParams object + * @return A boolean value telling whether video is enabled or not. +**/ +LINPHONE_PUBLIC bool_t linphone_call_params_video_enabled(const LinphoneCallParams *cp); + + +/******************************************************************************* + * Reference and user data handling functions * + ******************************************************************************/ + +/** + * Get the user data associated with the call params. + * @param[in] cl LinphoneCallParams object + * @return The user data associated with the call params. +**/ +LINPHONE_PUBLIC void *linphone_call_params_get_user_data(const LinphoneCallParams *cp); + +/** + * Assign a user data to the call params. + * @param[in] cl LinphoneCallParams object + * @param[in] ud The user data to associate with the call params. +**/ +LINPHONE_PUBLIC void linphone_call_params_set_user_data(LinphoneCallParams *cp, void *ud); + +/** + * Acquire a reference to the call params. + * @param[in] cl LinphoneCallParams object + * @return The same LinphoneCallParams object +**/ +LINPHONE_PUBLIC LinphoneCallParams * linphone_call_params_ref(LinphoneCallParams *cp); + +/** + * Release a reference to the call params. + * @param[in] cl LinphoneCallParams object +**/ +LINPHONE_PUBLIC void linphone_call_params_unref(LinphoneCallParams *cp); + + +/******************************************************************************* + * DEPRECATED * + ******************************************************************************/ + +/** @deprecated Use linphone_call_params_get_local_conference_mode() instead. */ +#define linphone_call_params_local_conference_mode linphone_call_params_get_local_conference_mode + +/** + * Destroy a LinphoneCallParams object. + * @param[in] cp LinphoneCallParams object + * @deprecated Use linphone_call_params_unref() instead. +**/ +LINPHONE_PUBLIC void linphone_call_params_destroy(LinphoneCallParams *cp); + + +/** + * @} +**/ + + +#endif /* __LINPHONE_CALL_PARAMS_H__ */ diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index c64a5d7e3..ef17b080b 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -35,7 +35,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. static void register_failure(SalOp *op); static int media_parameters_changed(LinphoneCall *call, SalMediaDescription *oldmd, SalMediaDescription *newmd) { - if (call->params.in_conference != call->current_params.in_conference) return SAL_MEDIA_DESCRIPTION_CHANGED; + if (call->params->in_conference != call->current_params->in_conference) return SAL_MEDIA_DESCRIPTION_CHANGED; if (call->up_bw != linphone_core_get_upload_bandwidth(call->core)) return SAL_MEDIA_DESCRIPTION_CHANGED; if (call->localdesc_changed) ms_message("Local description has changed: %i", call->localdesc_changed); return call->localdesc_changed | sal_media_description_equals(oldmd, newmd); @@ -96,7 +96,7 @@ static void prepare_early_media_forking(LinphoneCall *call){ if (call->videostream){ rtp_session_set_symmetric_rtp(call->videostream->ms.sessions.rtp_session,FALSE); } - + } void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMediaDescription *new_md){ @@ -163,7 +163,7 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia linphone_call_stop_media_streams (call); linphone_call_init_media_streams (call); } - + if (call->audiostream==NULL){ /*this happens after pausing the call locally. The streams are destroyed and then we wait the 200Ok to recreate them*/ linphone_call_init_media_streams (call); @@ -171,10 +171,10 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia if (call->state==LinphoneCallIncomingEarlyMedia && linphone_core_get_remote_ringback_tone (lc)!=NULL){ send_ringbacktone=TRUE; } - if ((call->state==LinphoneCallIncomingEarlyMedia || call->state==LinphoneCallOutgoingEarlyMedia) && !call->params.real_early_media){ + if ((call->state==LinphoneCallIncomingEarlyMedia || call->state==LinphoneCallOutgoingEarlyMedia) && !call->params->real_early_media){ all_muted=TRUE; } - if (call->params.real_early_media && call->state==LinphoneCallOutgoingEarlyMedia){ + if (call->params->real_early_media && call->state==LinphoneCallOutgoingEarlyMedia){ prepare_early_media_forking(call); } linphone_call_start_media_streams(call,all_muted,send_ringbacktone); @@ -182,9 +182,9 @@ void linphone_core_update_streams(LinphoneCore *lc, LinphoneCall *call, SalMedia linphone_core_play_named_tone(lc,LinphoneToneCallOnHold); } end: - if (oldmd) + if (oldmd) sal_media_description_unref(oldmd); - + } #if 0 static bool_t is_duplicate_call(LinphoneCore *lc, const LinphoneAddress *from, const LinphoneAddress *to){ @@ -192,7 +192,7 @@ static bool_t is_duplicate_call(LinphoneCore *lc, const LinphoneAddress *from, c for(elem=lc->calls;elem!=NULL;elem=elem->next){ LinphoneCall *call=(LinphoneCall*)elem->data; if (linphone_address_weak_equal(call->log->from,from) && - linphone_address_weak_equal(call->log->to, to)){ + linphone_address_weak_equal(call->log->to, to)){ return TRUE; } } @@ -220,11 +220,11 @@ static bool_t already_a_call_pending(LinphoneCore *lc){ for(elem=lc->calls;elem!=NULL;elem=elem->next){ LinphoneCall *call=(LinphoneCall*)elem->data; if (call->state==LinphoneCallIncomingReceived - || call->state==LinphoneCallIncomingEarlyMedia - || call->state==LinphoneCallOutgoingInit - || call->state==LinphoneCallOutgoingProgress - || call->state==LinphoneCallOutgoingEarlyMedia - || call->state==LinphoneCallOutgoingRinging){ + || call->state==LinphoneCallIncomingEarlyMedia + || call->state==LinphoneCallOutgoingInit + || call->state==LinphoneCallOutgoingProgress + || call->state==LinphoneCallOutgoingEarlyMedia + || call->state==LinphoneCallOutgoingRinging){ return TRUE; } } @@ -239,7 +239,7 @@ static void call_received(SalOp *h){ LinphoneAddress *from_addr, *to_addr; /*this mode is deprcated because probably useless*/ bool_t prevent_colliding_calls=lp_config_get_int(lc->config,"sip","prevent_colliding_calls",FALSE); - + /* first check if we can answer successfully to this invite */ if (linphone_presence_model_get_basic_status(lc->presence_model) == LinphonePresenceBasicStatusClosed) { LinphonePresenceActivity *activity = linphone_presence_model_get_activity(lc->presence_model); @@ -285,14 +285,14 @@ static void call_received(SalOp *h){ linphone_address_destroy(to_addr); return; } - + call=linphone_call_new_incoming(lc,from_addr,to_addr,h); - + /* the call is acceptable so we can now add it to our list */ linphone_core_add_call(lc,call); linphone_call_ref(call); /*prevent the call from being destroyed while we are notifying, if the user declines within the state callback */ - if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (call->ice_session != NULL)) { + if ((_linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && (call->ice_session != NULL)) { /* Defer ringing until the end of the ICE candidates gathering process. */ ms_message("Defer ringing to gather ICE candidates"); return; @@ -313,7 +313,7 @@ static void try_early_media_forking(LinphoneCall *call, SalMediaDescription *md) int i; SalStreamDescription *ref_stream,*new_stream; ms_message("Early media response received from another branch, checking if media can be forked to this new destination."); - + for (i=0;inb_streams;++i){ if (!sal_stream_description_active(&cur_md->streams[i])) continue; ref_stream=&cur_md->streams[i]; @@ -345,15 +345,14 @@ static void call_ringing(SalOp *h){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h)); LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(h); SalMediaDescription *md; - - if (call==NULL) return; - - /*set privacy*/ - call->current_params.privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op); - if (lc->vtable.display_status) - lc->vtable.display_status(lc,_("Remote ringing.")); - + if (call==NULL) return; + + /*set privacy*/ + call->current_params->privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op); + + linphone_core_notify_display_status(lc,_("Remote ringing.")); + md=sal_call_get_final_media_description(h); if (md==NULL){ linphone_core_stop_dtmf_stream(lc); @@ -364,11 +363,12 @@ static void call_ringing(SalOp *h){ /*we release sound before playing ringback tone*/ if (call->audiostream) audio_stream_unprepare_sound(call->audiostream); - lc->ringstream=ring_start(lc->sound_conf.remote_ring,2000,ringcard); + if( lc->sound_conf.remote_ring ){ + lc->ringstream=ring_start(lc->sound_conf.remote_ring,2000,ringcard); + } } ms_message("Remote ringing..."); - if (lc->vtable.display_status) - lc->vtable.display_status(lc,_("Remote ringing...")); + linphone_core_notify_display_status(lc,_("Remote ringing...")); linphone_call_set_state(call,LinphoneCallOutgoingRinging,"Remote ringing"); }else{ /*accept early media */ @@ -377,9 +377,8 @@ static void call_ringing(SalOp *h){ try_early_media_forking(call,md); return; } - if (lc->vtable.show) lc->vtable.show(lc); - if (lc->vtable.display_status) - lc->vtable.display_status(lc,_("Early media.")); + linphone_core_notify_show_interface(lc); + linphone_core_notify_display_status(lc,_("Early media.")); linphone_call_set_state(call,LinphoneCallOutgoingEarlyMedia,"Early media"); linphone_core_stop_ringing(lc); ms_message("Doing early media..."); @@ -396,13 +395,13 @@ static void call_accepted(SalOp *op){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); SalMediaDescription *md; - + if (call==NULL){ ms_warning("No call to accept."); return ; } /*set privacy*/ - call->current_params.privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op); + call->current_params->privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op); /* Handle remote ICE attributes if any. */ if (call->ice_session != NULL) { @@ -416,22 +415,22 @@ static void call_accepted(SalOp *op){ md=sal_call_get_final_media_description(op); if (md) /*make sure re-invite will not propose video again*/ - call->params.has_video &= linphone_core_media_description_contains_video_stream(md); - + call->params->has_video &= linphone_core_media_description_contains_video_stream(md); + if (call->state==LinphoneCallOutgoingProgress || - call->state==LinphoneCallOutgoingRinging || - call->state==LinphoneCallOutgoingEarlyMedia){ + call->state==LinphoneCallOutgoingRinging || + call->state==LinphoneCallOutgoingEarlyMedia){ linphone_call_set_state(call,LinphoneCallConnected,"Connected"); if (call->referer) linphone_core_notify_refer_state(lc,call->referer,call); } if (md && !sal_media_description_empty(md) && !linphone_core_incompatible_security(lc,md)){ linphone_call_update_remote_session_id_and_ver(call); if (sal_media_description_has_dir(md,SalStreamSendOnly) || - sal_media_description_has_dir(md,SalStreamInactive)){ - if (lc->vtable.display_status){ + sal_media_description_has_dir(md,SalStreamInactive)){ + { char *tmp=linphone_call_get_remote_address_as_string (call); char *msg=ms_strdup_printf(_("Call with %s is paused."),tmp); - lc->vtable.display_status(lc,msg); + linphone_core_notify_display_status(lc,msg); ms_free(tmp); ms_free(msg); } @@ -441,10 +440,10 @@ static void call_accepted(SalOp *op){ linphone_core_start_refered_call(lc,call,NULL); }else if (sal_media_description_has_dir(md,SalStreamRecvOnly)){ /*we are put on hold when the call is initially accepted */ - if (lc->vtable.display_status){ + { char *tmp=linphone_call_get_remote_address_as_string (call); char *msg=ms_strdup_printf(_("Call answered by %s - on hold."),tmp); - lc->vtable.display_status(lc,msg); + linphone_core_notify_display_status(lc,msg); ms_free(tmp); ms_free(msg); } @@ -453,14 +452,12 @@ static void call_accepted(SalOp *op){ }else{ if (call->state!=LinphoneCallUpdating){ if (call->state==LinphoneCallResuming){ - if (lc->vtable.display_status){ - lc->vtable.display_status(lc,_("Call resumed.")); - } + linphone_core_notify_display_status(lc,_("Call resumed.")); }else{ - if (lc->vtable.display_status){ + { char *tmp=linphone_call_get_remote_address_as_string (call); char *msg=ms_strdup_printf(_("Call answered by %s."),tmp); - lc->vtable.display_status(lc,msg); + linphone_core_notify_display_status(lc,msg); ms_free(tmp); ms_free(msg); } @@ -470,7 +467,7 @@ static void call_accepted(SalOp *op){ /*also reflect the change if the "wished" params, in order to avoid to propose SAVP or video again * further in the call, for example during pause,resume, conferencing reINVITEs*/ linphone_call_fix_call_parameters(call); - if (!call->current_params.in_conference) + if (!call->current_params->in_conference) lc->current_call=call; if (call->prevstate != LinphoneCallIncomingEarlyMedia) /*don't change state in aswer to a SIP UPDATE in early media*/ linphone_call_set_state(call, LinphoneCallStreamsRunning, "Streams running"); @@ -503,81 +500,73 @@ static void call_ack(SalOp *op){ } } -static void call_accept_update(LinphoneCore *lc, LinphoneCall *call){ - SalMediaDescription *md; - SalMediaDescription *rmd=sal_call_get_remote_media_description(call->op); - if (rmd!=NULL && call->ice_session!=NULL) { - linphone_core_update_ice_from_remote_media_description(call,rmd); - linphone_core_update_local_media_description_from_ice(call->localdesc,call->ice_session); - } -#ifdef BUILD_UPNP - if(call->upnp_session != NULL) { - linphone_core_update_upnp_from_remote_media_description(call, rmd); - linphone_core_update_local_media_description_from_upnp(call->localdesc,call->upnp_session); - } -#endif //BUILD_UPNP - linphone_call_update_remote_session_id_and_ver(call); - sal_call_accept(call->op); - md=sal_call_get_final_media_description(call->op); - if (md && !sal_media_description_empty(md)){ - linphone_core_update_streams(lc,call,md); - } -} - static void call_resumed(LinphoneCore *lc, LinphoneCall *call){ /*when we are resumed, increment session id, because sdp is changed (a=recvonly disapears)*/ linphone_call_increment_local_media_description(call); - call_accept_update(lc,call); - if(lc->vtable.display_status) - lc->vtable.display_status(lc,_("We have been resumed.")); - linphone_call_set_state(call,LinphoneCallStreamsRunning,"Connected (streams running)"); + linphone_core_notify_display_status(lc,_("We have been resumed.")); + _linphone_core_accept_call_update(lc,call,NULL,LinphoneCallStreamsRunning,"Connected (streams running)"); } static void call_paused_by_remote(LinphoneCore *lc, LinphoneCall *call){ - /*when we are resumed, increment session id, because sdp is changed (a=recvonly appears)*/ + /*when we are paused, increment session id, because sdp is changed (a=recvonly appears)*/ linphone_call_increment_local_media_description(call); - call_accept_update(lc,call); /* we are being paused */ - if(lc->vtable.display_status) - lc->vtable.display_status(lc,_("We are paused by other party.")); - linphone_call_set_state (call,LinphoneCallPausedByRemote,"Call paused by remote"); + linphone_core_notify_display_status(lc,_("We are paused by other party.")); + _linphone_core_accept_call_update(lc,call,NULL,LinphoneCallPausedByRemote,"Call paused by remote"); + } -static void call_updated_by_remote(LinphoneCore *lc, LinphoneCall *call,bool_t notify_application){ +static void call_updated_by_remote(LinphoneCore *lc, LinphoneCall *call, bool_t is_update){ /*first check if media capabilities are compatible*/ - SalMediaDescription* md; - linphone_call_make_local_media_description(lc,call); - sal_call_set_local_media_description(call->op,call->localdesc); - md=sal_call_get_final_media_description(call->op); - if (md && (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md))){ - sal_call_decline(call->op,SalReasonNotAcceptable,NULL); - return; + SalMediaDescription *md; + SalMediaDescription *rmd=sal_call_get_remote_media_description(call->op); + SalMediaDescription *prev_result_desc=call->resultdesc; + + if (rmd!=NULL){ + if (call->state!=LinphoneCallPaused){ + /*in paused state, we must stay in paused state.*/ + linphone_call_make_local_media_description(lc,call); + sal_call_set_local_media_description(call->op,call->localdesc); + } + md=sal_call_get_final_media_description(call->op); + if (md && (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md))){ + sal_call_decline(call->op,SalReasonNotAcceptable,NULL); + return; + } + if (is_update && prev_result_desc && md){ + int diff=sal_media_description_equals(prev_result_desc,md); + if (diff & (SAL_MEDIA_DESCRIPTION_CRYPTO_CHANGED|SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED)){ + ms_warning("Cannot accept this update, it is changing parameters that require user approval"); + sal_call_decline(call->op,SalReasonNotAcceptable,NULL); /*FIXME should send 504 Cannot change the session parameters without prompting the user"*/ + return; + } + } } - if (notify_application) { - if(lc->vtable.display_status) - lc->vtable.display_status(lc,_("Call is updated by remote.")); + if (call->state==LinphoneCallStreamsRunning) { + /*reINVITE and in-dialogs UPDATE go here*/ + linphone_core_notify_display_status(lc,_("Call is updated by remote.")); call->defer_update=FALSE; linphone_call_set_state(call, LinphoneCallUpdatedByRemote,"Call updated by remote"); if (call->defer_update==FALSE){ linphone_core_accept_call_update(lc,call,NULL); } - } else { /*SIP UPDATE case*/ - /*can be call from any state*/ - _linphone_core_accept_call_update(lc,call,NULL); + if (rmd==NULL) + call->expect_media_in_ack=TRUE; + } else if (is_update){ /*SIP UPDATE case, can occur in early states*/ + _linphone_core_accept_call_update(lc,call,NULL,call->state,linphone_call_state_to_string(call->state)); } } /* this callback is called when an incoming re-INVITE/ SIP UPDATE modifies the session*/ -static void call_updating(SalOp *op){ +static void call_updating(SalOp *op, bool_t is_update){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); SalMediaDescription *rmd=sal_call_get_remote_media_description(op); if (rmd==NULL){ - /* case of a reINVITE without SDP */ - call_accept_update(lc,call); - call->expect_media_in_ack=TRUE; + /* case of a reINVITE or UPDATE without SDP */ + call_updated_by_remote(lc,call,is_update); return; } @@ -585,22 +574,45 @@ static void call_updating(SalOp *op){ case LinphoneCallPausedByRemote: if (sal_media_description_has_dir(rmd,SalStreamSendRecv) || sal_media_description_has_dir(rmd,SalStreamRecvOnly)){ call_resumed(lc,call); - }else call_paused_by_remote(lc,call); + }else call_updated_by_remote(lc,call,is_update); break; /*SIP UPDATE CASE*/ + case LinphoneCallOutgoingRinging: case LinphoneCallOutgoingEarlyMedia: - call_updated_by_remote(lc,call,FALSE); + case LinphoneCallIncomingEarlyMedia: + if (is_update) call_updated_by_remote(lc,call,is_update); break; case LinphoneCallStreamsRunning: case LinphoneCallConnected: if (sal_media_description_has_dir(rmd,SalStreamSendOnly) || sal_media_description_has_dir(rmd,SalStreamInactive)){ call_paused_by_remote(lc,call); }else{ - call_updated_by_remote(lc,call,TRUE); + call_updated_by_remote(lc,call,is_update); } break; - default: - call_accept_update(lc,call); + case LinphoneCallPaused: + if (sal_media_description_has_dir(rmd,SalStreamSendOnly) || sal_media_description_has_dir(rmd,SalStreamInactive)){ + call_paused_by_remote(lc,call); + }else{ + call_updated_by_remote(lc,call,is_update); + } + break; + case LinphoneCallUpdating: + case LinphoneCallPausing: + case LinphoneCallResuming: + case LinphoneCallUpdatedByRemote: + sal_call_decline(call->op,SalReasonNotImplemented,NULL); + /*no break*/ + case LinphoneCallIdle: + case LinphoneCallOutgoingInit: + case LinphoneCallEnd: + case LinphoneCallIncomingReceived: + case LinphoneCallOutgoingProgress: + case LinphoneCallRefered: + case LinphoneCallError: + case LinphoneCallReleased: + ms_warning("Receiving reINVITE or UPDATE while in state [%s], should not happen.",linphone_call_state_to_string(call->state)); + break; } } @@ -609,7 +621,7 @@ static void call_terminated(SalOp *op, const char *from){ LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); if (call==NULL) return; - + switch(linphone_call_get_state(call)){ case LinphoneCallEnd: case LinphoneCallError: @@ -632,10 +644,8 @@ static void call_terminated(SalOp *op, const char *from){ linphone_core_stop_ringing(lc); } linphone_call_stop_media_streams(call); - if (lc->vtable.show!=NULL) - lc->vtable.show(lc); - if (lc->vtable.display_status!=NULL) - lc->vtable.display_status(lc,_("Call terminated.")); + linphone_core_notify_show_interface(lc); + linphone_core_notify_display_status(lc,_("Call terminated.")); #ifdef BUILD_UPNP linphone_call_delete_upnp_session(call); @@ -648,7 +658,7 @@ static int resume_call_after_failed_transfer(LinphoneCall *call){ ms_message("!!!!!!!!!!resume_call_after_failed_transfer"); if (call->was_automatically_paused && call->state==LinphoneCallPausing) return BELLE_SIP_CONTINUE; /*was still in pausing state*/ - + if (call->was_automatically_paused && call->state==LinphoneCallPaused){ if (sal_op_is_idle(call->op)){ linphone_core_resume_call(call->core,call); @@ -677,25 +687,22 @@ static void call_failure(SalOp *op){ ms_warning("Call faillure reported on already terminated call."); return ; } - - if (lc->vtable.show) lc->vtable.show(lc); + + linphone_core_notify_show_interface(lc); switch(ei->reason){ case SalReasonNone: break; case SalReasonRequestTimeout: msg=_("Request timeout."); - if (lc->vtable.display_status) - lc->vtable.display_status(lc,msg); + linphone_core_notify_display_status(lc,msg); break; case SalReasonDeclined: msg=msg603; - if (lc->vtable.display_status) - lc->vtable.display_status(lc,msg603); + linphone_core_notify_display_status(lc,msg603); break; case SalReasonBusy: msg=msg486; - if (lc->vtable.display_status) - lc->vtable.display_status(lc,msg486); + linphone_core_notify_display_status(lc,msg486); break; case SalReasonRedirect: { @@ -715,23 +722,19 @@ static void call_failure(SalOp *op){ } } msg=_("Redirected"); - if (lc->vtable.display_status) - lc->vtable.display_status(lc,msg); + linphone_core_notify_display_status(lc,msg); } break; case SalReasonTemporarilyUnavailable: msg=msg480; - if (lc->vtable.display_status) - lc->vtable.display_status(lc,msg480); + linphone_core_notify_display_status(lc,msg480); break; case SalReasonNotFound: - if (lc->vtable.display_status) - lc->vtable.display_status(lc,msg); + linphone_core_notify_display_status(lc,msg); break; case SalReasonDoNotDisturb: msg=msg600; - if (lc->vtable.display_status) - lc->vtable.display_status(lc,msg600); + linphone_core_notify_display_status(lc,msg600); break; case SalReasonUnsupportedContent: /*localdesc->nb_streams; i++) { if (!sal_stream_description_active(&call->localdesc->streams[i])) continue; - if (call->params.media_encryption == LinphoneMediaEncryptionSRTP) { - if (call->params.avpf_enabled == TRUE) { + if (call->params->media_encryption == LinphoneMediaEncryptionSRTP) { + if (call->params->avpf_enabled == TRUE) { if (i == 0) ms_message("Retrying call [%p] with SAVP", call); - call->params.avpf_enabled = FALSE; + call->params->avpf_enabled = FALSE; linphone_core_restart_invite(lc, call); return; } else if (!linphone_core_is_media_encryption_mandatory(lc)) { if (i == 0) ms_message("Retrying call [%p] with AVP", call); - call->params.media_encryption = LinphoneMediaEncryptionNone; + call->params->media_encryption = LinphoneMediaEncryptionNone; memset(call->localdesc->streams[i].crypto, 0, sizeof(call->localdesc->streams[i].crypto)); linphone_core_restart_invite(lc, call); return; } - } else if (call->params.avpf_enabled == TRUE) { + } else if (call->params->avpf_enabled == TRUE) { if (i == 0) ms_message("Retrying call [%p] with AVP", call); - call->params.avpf_enabled = FALSE; + call->params->avpf_enabled = FALSE; linphone_core_restart_invite(lc, call); return; } } } msg=_("Incompatible media parameters."); - if (lc->vtable.display_status) - lc->vtable.display_status(lc,msg); + linphone_core_notify_display_status(lc,msg); break; case SalReasonRequestPending: /*restore previous state, the application will decide to resubmit the action if relevant*/ @@ -774,8 +776,7 @@ static void call_failure(SalOp *op){ return; break; default: - if (lc->vtable.display_status) - lc->vtable.display_status(lc,_("Call failed.")); + linphone_core_notify_display_status(lc,_("Call failed.")); } /*some call error are not fatal*/ @@ -796,7 +797,7 @@ static void call_failure(SalOp *op){ #ifdef BUILD_UPNP linphone_call_delete_upnp_session(call); #endif //BUILD_UPNP - + if (call->state!=LinphoneCallEnd && call->state!=LinphoneCallError){ if (ei->reason==SalReasonDeclined){ linphone_call_set_state(call,LinphoneCallEnd,"Call declined."); @@ -805,7 +806,7 @@ static void call_failure(SalOp *op){ } if (ei->reason!=SalReasonNone) linphone_core_play_call_error_tone(lc,linphone_reason_from_sal(ei->reason)); } - + if (referer){ /*notify referer of the failure*/ linphone_core_notify_refer_state(lc,referer,call); @@ -827,35 +828,38 @@ static void call_released(SalOp *op){ static void auth_failure(SalOp *op, SalAuthInfo* info) { LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); - LinphoneAuthInfo *ai=(LinphoneAuthInfo*)linphone_core_find_auth_info(lc,info->realm,info->username,info->domain); - if (ai){ - ms_message("%s/%s/%s authentication fails.",info->realm,info->username,info->domain); - /*ask again for password if auth info was already supplied but apparently not working*/ - if (lc->vtable.auth_info_requested) { - lc->vtable.auth_info_requested(lc,info->realm,info->username,info->domain); + LinphoneAuthInfo *ai=NULL; + + if( info != NULL ){ + ai = (LinphoneAuthInfo*)linphone_core_find_auth_info(lc,info->realm,info->username,info->domain); + + if (ai){ + ms_message("%s/%s/%s authentication fails.",info->realm,info->username,info->domain); + /*ask again for password if auth info was already supplied but apparently not working*/ + linphone_core_notify_auth_info_requested(lc,info->realm,info->username,info->domain); } } - + } static void register_success(SalOp *op, bool_t registered){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)sal_op_get_user_pointer(op); char *msg; - - if (!cfg || cfg->deletion_date!=0){ - ms_message("Registration success for removed proxy config, ignored"); + + if (!cfg){ + ms_message("Registration success for deleted proxy config, ignored"); return; } linphone_proxy_config_set_state(cfg, registered ? LinphoneRegistrationOk : LinphoneRegistrationCleared , - registered ? "Registration successful" : "Unregistration done"); - if (lc->vtable.display_status){ + registered ? "Registration successful" : "Unregistration done"); + { if (registered) msg=ms_strdup_printf(_("Registration on %s successful."),sal_op_get_proxy(op)); else msg=ms_strdup_printf(_("Unregistration on %s done."),sal_op_get_proxy(op)); - lc->vtable.display_status(lc,msg); + linphone_core_notify_display_status(lc,msg); ms_free(msg); } - + } static void register_failure(SalOp *op){ @@ -868,16 +872,12 @@ static void register_failure(SalOp *op){ ms_warning("Registration failed for unknown proxy config."); return ; } - if (cfg->deletion_date!=0){ - ms_message("Registration failed for removed proxy config, ignored"); - return; - } if (details==NULL) details=_("no response timeout"); - - if (lc->vtable.display_status) { + + { char *msg=ortp_strdup_printf(_("Registration on %s failed: %s"),sal_op_get_proxy(op), details); - lc->vtable.display_status(lc,msg); + linphone_core_notify_display_status(lc,msg); ms_free(msg); } @@ -910,8 +910,7 @@ static void vfu_request(SalOp *op){ static void dtmf_received(SalOp *op, char dtmf){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); - if (lc->vtable.dtmf_received != NULL) - lc->vtable.dtmf_received(lc, call, dtmf); + linphone_core_notify_dtmf_received(lc, call, dtmf); } static void refer_received(Sal *sal, SalOp *op, const char *referto){ @@ -924,14 +923,14 @@ static void refer_received(Sal *sal, SalOp *op, const char *referto){ call->refer_to=ms_strdup(referto); call->refer_pending=TRUE; linphone_call_set_state(call,LinphoneCallRefered,"Refered"); - if (lc->vtable.display_status){ + { char *msg=ms_strdup_printf(_("We are transferred to %s"),referto); - lc->vtable.display_status(lc,msg); + linphone_core_notify_display_status(lc,msg); ms_free(msg); } if (call->refer_pending) linphone_core_start_refered_call(lc,call,NULL); - }else if (lc->vtable.refer_received){ - lc->vtable.refer_received(lc,referto); + }else { + linphone_core_notify_refer_received(lc,referto); } } @@ -1051,8 +1050,8 @@ static bool_t auth_requested(Sal* sal, SalAuthInfo* sai) { if (fill_auth_info(lc,sai)) { return TRUE; } else { - if (lc->vtable.auth_info_requested) { - lc->vtable.auth_info_requested(lc,sai->realm,sai->username,sai->domain); + { + linphone_core_notify_auth_info_requested(lc,sai->realm,sai->username,sai->domain); if (fill_auth_info(lc,sai)) { return TRUE; } @@ -1135,9 +1134,9 @@ static void info_received(SalOp *op, const SalBody *body){ static void subscribe_response(SalOp *op, SalSubscribeStatus status){ LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); const SalErrorInfo *ei=sal_op_get_error_info(op); - + if (lev==NULL) return; - + if (status==SalSubscribeActive){ linphone_event_set_state(lev,LinphoneSubscriptionActive); }else if (status==SalSubscribePending){ @@ -1153,15 +1152,15 @@ static void subscribe_response(SalOp *op, SalSubscribeStatus status){ static void notify(SalOp *op, SalSubscribeStatus st, const char *eventname, const SalBody *body){ LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); - LinphoneContent content; - + LinphoneContent content={0}; + if (lev==NULL) { /*out of subscribe notify */ lev=linphone_event_new_with_out_of_dialog_op(lc,op,LinphoneSubscriptionOutgoing,eventname); } - if (lc->vtable.notify_received){ + { const LinphoneContent *ct=linphone_content_from_sal_body(&content,body); - if (ct) lc->vtable.notify_received(lc,lev,eventname,ct); + if (ct) linphone_core_notify_notify_received(lc,lev,eventname,ct); } if (st!=SalSubscribeNone){ linphone_event_set_state(lev,linphone_subscription_state_from_sal(st)); @@ -1171,31 +1170,31 @@ static void notify(SalOp *op, SalSubscribeStatus st, const char *eventname, cons static void subscribe_received(SalOp *op, const char *eventname, const SalBody *body){ LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); - + if (lev==NULL) { lev=linphone_event_new_with_op(lc,op,LinphoneSubscriptionIncoming,eventname); linphone_event_set_state(lev,LinphoneSubscriptionIncomingReceived); }else{ /*subscribe refresh, unhandled*/ } - + } static void subscribe_closed(SalOp *op){ LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); - + linphone_event_set_state(lev,LinphoneSubscriptionTerminated); } static void on_publish_response(SalOp* op){ LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); const SalErrorInfo *ei=sal_op_get_error_info(op); - + if (lev==NULL) return; if (ei->reason==SalReasonNone){ if (!lev->terminating) linphone_event_set_publish_state(lev,LinphonePublishOk); - else + else linphone_event_set_publish_state(lev,LinphonePublishCleared); }else{ if (lev->publish_state==LinphonePublishOk){ @@ -1208,9 +1207,9 @@ static void on_publish_response(SalOp* op){ static void on_expire(SalOp *op){ LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); - + if (lev==NULL) return; - + if (linphone_event_get_publish_state(lev)==LinphonePublishOk){ linphone_event_set_publish_state(lev,LinphonePublishExpiring); }else if (linphone_event_get_subscription_state(lev)==LinphoneSubscriptionActive){ diff --git a/coreapi/chat.c b/coreapi/chat.c index 73f4d8da8..582638210 100644 --- a/coreapi/chat.c +++ b/coreapi/chat.c @@ -39,22 +39,37 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage* msg); #define MULTIPART_BOUNDARY "---------------------------14737809831466499882746641449" -#define FILEPART_HEADER_1 "Content-Disposition: form-data; name=\"File\"; filename=\"" -#define FILEPART_HEADER_2 "\"\r\n" \ - "Content-Type: " -#define FILEPART_HEADER_3 "\r\n\r\n" const char *multipart_boundary=MULTIPART_BOUNDARY; -#define FILE_TRANSFER_KEY_SIZE 32 -static size_t linphone_chat_message_compute_filepart_header_size(const char *filename, const char *content_type) { - return strlen(FILEPART_HEADER_1)+strlen(filename)+strlen(FILEPART_HEADER_2)+strlen(content_type)+strlen(FILEPART_HEADER_3); -} -static void process_io_error(void *data, const belle_sip_io_error_event_t *event){ +static void process_io_error_upload(void *data, const belle_sip_io_error_event_t *event){ LinphoneChatMessage* msg=(LinphoneChatMessage *)data; - msg->cb(msg, LinphoneChatMessageStateNotDelivered, msg->chat_room->lc); + ms_error("I/O Error during file upload to %s - msg [%p] chat room[%p]", msg->chat_room->lc->file_transfer_server, msg, msg->chat_room); + if (msg->cb) { + msg->cb(msg, LinphoneChatMessageStateNotDelivered, msg->chat_room->lc); + } +#define FILE_TRANSFER_KEY_SIZE 32 } -static void process_auth_requested(void *data, belle_sip_auth_event_t *event){ - printf("We have a auth requested!\n"); +static void process_auth_requested_upload(void *data, belle_sip_auth_event_t *event){ + LinphoneChatMessage* msg=(LinphoneChatMessage *)data; + ms_error("Error during file upload : auth requested to connect %s - msg [%p] chat room[%p]", msg->chat_room->lc->file_transfer_server, msg, msg->chat_room); + if (msg->cb) { + msg->cb(msg, LinphoneChatMessageStateNotDelivered, msg->chat_room->lc); + } +} + +static void process_io_error_download(void *data, const belle_sip_io_error_event_t *event){ + LinphoneChatMessage* msg=(LinphoneChatMessage *)data; + ms_error("I/O Error during file download %s - msg [%p] chat room[%p]", msg->external_body_url, msg, msg->chat_room); + if (msg->cb) { + msg->cb(msg, LinphoneChatMessageStateFileTransferError, msg->chat_room->lc); + } +} +static void process_auth_requested_download(void *data, belle_sip_auth_event_t *event){ + LinphoneChatMessage* msg=(LinphoneChatMessage *)data; + ms_error("Error during file download : auth requested to get %s - msg [%p] chat room[%p]", msg->external_body_url, msg, msg->chat_room); + if (msg->cb) { + msg->cb(msg, LinphoneChatMessageStateFileTransferError, msg->chat_room->lc); + } } /** @@ -65,9 +80,7 @@ static void linphone_chat_message_file_transfer_on_progress(belle_sip_body_handl LinphoneChatMessage* chatMsg=(LinphoneChatMessage *)data; LinphoneCore *lc = chatMsg->chat_room->lc; /* call back given by application level */ - if (lc->vtable.file_transfer_progress_indication != NULL) { - lc->vtable.file_transfer_progress_indication(lc, chatMsg, chatMsg->file_transfer_information, (size_t)(((double)offset/(double)total)*100.0)); - } + linphone_core_notify_file_transfer_progress_indication(lc, chatMsg, chatMsg->file_transfer_information, (size_t)(((double)offset/(double)total)*100.0)); return; } @@ -86,24 +99,11 @@ static int linphone_chat_message_file_transfer_on_send_body(belle_sip_user_body_ LinphoneChatMessage* chatMsg=(LinphoneChatMessage *)data; LinphoneCore *lc = chatMsg->chat_room->lc; char *buf = (char *)buffer; - - char *content_type=belle_sip_strdup_printf("%s/%s", chatMsg->file_transfer_information->type, chatMsg->file_transfer_information->subtype); size_t end_of_file=linphone_chat_message_compute_filepart_header_size(chatMsg->file_transfer_information->name, content_type)+chatMsg->file_transfer_information->size; - if (offset==0){ - int partlen=linphone_chat_message_compute_filepart_header_size(chatMsg->file_transfer_information->name, content_type); - memcpy(buf,FILEPART_HEADER_1,strlen(FILEPART_HEADER_1)); - buf += strlen(FILEPART_HEADER_1); - memcpy(buf,chatMsg->file_transfer_information->name,strlen(chatMsg->file_transfer_information->name)); - buf += strlen(chatMsg->file_transfer_information->name); - memcpy(buf,FILEPART_HEADER_2,strlen(FILEPART_HEADER_2)); - buf += strlen(FILEPART_HEADER_2); - memcpy(buf,content_type,strlen(content_type)); - buf += strlen(content_type); - memcpy(buf,FILEPART_HEADER_3,strlen(FILEPART_HEADER_3)); - - *size=partlen; - }else if (offsetfile_transfer_information->size){ + if (chatMsg->file_transfer_information->key != NULL) { /* if we have a key to cipher the message, use it! */ /* get data from callback to a plainBuffer */ /* if this chunk is not the last one, the lenght must be a multiple of block cipher size(16 bytes)*/ @@ -111,12 +111,12 @@ static int linphone_chat_message_file_transfer_on_send_body(belle_sip_user_body_ *size -=(*size%16); } char *plainBuffer = (char *)malloc(*size); - lc->vtable.file_transfer_send(lc, chatMsg, chatMsg->file_transfer_information, plainBuffer, size); + linphone_core_notify_file_transfer_send(lc, chatMsg, chatMsg->file_transfer_information, buf, size); lime_encryptFile(&(chatMsg->file_transfer_information->cryptoContext), chatMsg->file_transfer_information->key, *size, plainBuffer, (char*)buffer); free(plainBuffer); } else { /* get data from call back directly to the output buffer */ - lc->vtable.file_transfer_send(lc, chatMsg, chatMsg->file_transfer_information, (char*)buffer, size); + linphone_core_notify_file_transfer_send(lc, chatMsg, chatMsg->file_transfer_information, buf, size); } /* DEBUG DEBUG : THIS SHALL NEVER HAPPEND */ if (*size == 0) { @@ -129,7 +129,6 @@ static int linphone_chat_message_file_transfer_on_send_body(belle_sip_user_body_ } } - belle_sip_free(content_type); return BELLE_SIP_CONTINUE; } @@ -159,18 +158,26 @@ static void linphone_chat_message_process_response_from_post_file(void *data, co belle_http_request_listener_t *l; belle_generic_uri_t *uri; belle_http_request_t *req; - char *content_type=belle_sip_strdup_printf("%s/%s", msg->file_transfer_information->type, msg->file_transfer_information->subtype); + belle_sip_multipart_body_handler_t *bh; + char* ua; + char *content_type; + char *first_part_header; + belle_sip_user_body_handler_t *first_part_bh; - /* create a user body handler to take care of the file */ - size_t body_size = msg->file_transfer_information->size+linphone_chat_message_compute_filepart_header_size(msg->file_transfer_information->name, content_type); + /* temporary storage for the Content-disposition header value */ + first_part_header = belle_sip_strdup_printf("form-data; name=\"File\"; filename=\"%s\"", msg->file_transfer_information->name); + + /* create a user body handler to take care of the file and add the content disposition and content-type headers */ + first_part_bh=belle_sip_user_body_handler_new(msg->file_transfer_information->size,NULL,NULL,linphone_chat_message_file_transfer_on_send_body,msg); + belle_sip_body_handler_add_header((belle_sip_body_handler_t *)first_part_bh, belle_sip_header_create("Content-disposition", first_part_header)); + belle_sip_free(first_part_header); + belle_sip_body_handler_add_header((belle_sip_body_handler_t *)first_part_bh, (belle_sip_header_t *)belle_sip_header_content_type_create(msg->file_transfer_information->type, msg->file_transfer_information->subtype)); - belle_sip_user_body_handler_t *first_part_bh=belle_sip_user_body_handler_new(body_size,NULL,NULL,linphone_chat_message_file_transfer_on_send_body,msg); /* insert it in a multipart body handler which will manage the boundaries of multipart message */ - belle_sip_multipart_body_handler_t *bh=belle_sip_multipart_body_handler_new(linphone_chat_message_file_transfer_on_progress, msg, (belle_sip_body_handler_t *)first_part_bh); + bh=belle_sip_multipart_body_handler_new(linphone_chat_message_file_transfer_on_progress, msg, (belle_sip_body_handler_t *)first_part_bh); - char* ua = ms_strdup_printf("%s/%s", linphone_core_get_user_agent_name(), linphone_core_get_user_agent_version()); + ua = ms_strdup_printf("%s/%s", linphone_core_get_user_agent_name(), linphone_core_get_user_agent_version()); - belle_sip_free(content_type); content_type=belle_sip_strdup_printf("multipart/form-data; boundary=%s",multipart_boundary); uri=belle_generic_uri_parse(msg->chat_room->lc->file_transfer_server); @@ -184,13 +191,19 @@ static void linphone_chat_message_process_response_from_post_file(void *data, co belle_sip_free(content_type); belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(req),BELLE_SIP_BODY_HANDLER(bh)); cbs.process_response=linphone_chat_message_process_response_from_post_file; - cbs.process_io_error=process_io_error; - cbs.process_auth_requested=process_auth_requested; + cbs.process_io_error=process_io_error_upload; + cbs.process_auth_requested=process_auth_requested_upload; l=belle_http_request_listener_create_from_callbacks(&cbs,msg); + msg->http_request=req; /* update the reference to the http request to be able to cancel it during upload */ belle_http_provider_send_request(msg->chat_room->lc->http_provider,req,l); } + if (code == 200 ) { /* file has been uplaoded correctly, get server reply and send it */ const char *body = belle_sip_message_get_body((belle_sip_message_t *)event->response); + + /* TODO Check that the transfer has not been cancelled, note this shall be removed once the belle sip API will provide a cancel request as we shall never reach this part if the transfer is actually cancelled */ + if (msg->http_request == NULL) { + return; /* if we have an encryption key for the file, we must insert it into the message */ if (msg->file_transfer_information->key != NULL) { @@ -230,10 +243,6 @@ static void linphone_chat_message_process_response_from_post_file(void *data, co } else { /* no encryption key, transfer in plain, just copy the message sent by server */ msg->message = ms_strdup(body); } - - linphone_content_uninit(msg->file_transfer_information); - ms_free(msg->file_transfer_information); - msg->file_transfer_information = NULL; msg->content_type = ms_strdup("application/vnd.gsma.rcs-ft-http+xml"); _linphone_chat_room_send_message(msg->chat_room, msg); } @@ -286,44 +295,59 @@ bool_t linphone_core_chat_enabled(const LinphoneCore *lc){ /** * Returns an list of chat rooms - * @param lc #LinphoneCore object - * @return A list of #LinphoneChatRoom + * @param[in] lc #LinphoneCore object + * @return \mslist{LinphoneChatRoom} **/ MSList* linphone_core_get_chat_rooms(LinphoneCore *lc) { return lc->chatrooms; } -/** - * Create a new chat room for messaging from a sip uri like sip:joe@sip.linphone.org - * @param lc #LinphoneCore object - * @param to destination address for messages - * @return #LinphoneChatRoom where messaging can take place. - */ -LinphoneChatRoom * linphone_core_create_chat_room(LinphoneCore *lc, const char *to){ - LinphoneAddress *parsed_url=NULL; +static bool_t linphone_chat_room_matches(LinphoneChatRoom *cr, const LinphoneAddress *from){ + return linphone_address_weak_equal(cr->peer_url,from); +} - if ((parsed_url=linphone_core_interpret_url(lc,to))!=NULL){ - LinphoneChatRoom *cr=ms_new0(LinphoneChatRoom,1); - cr->lc=lc; - cr->peer=linphone_address_as_string(parsed_url); - cr->peer_url=parsed_url; - lc->chatrooms=ms_list_append(lc->chatrooms,(void *)cr); - return cr; +static void _linphone_chat_room_destroy(LinphoneChatRoom *obj); + +BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneChatRoom); + +BELLE_SIP_INSTANCIATE_VPTR(LinphoneChatRoom, belle_sip_object_t, + (belle_sip_object_destroy_t)_linphone_chat_room_destroy, + NULL, // clone + NULL, // marshal + FALSE +); + +static LinphoneChatRoom * _linphone_core_create_chat_room(LinphoneCore *lc, LinphoneAddress *addr) { + LinphoneChatRoom *cr = belle_sip_object_new(LinphoneChatRoom); + cr->lc = lc; + cr->peer = linphone_address_as_string(addr); + cr->peer_url = addr; + lc->chatrooms = ms_list_append(lc->chatrooms, (void *)cr); + return cr; +} + +static LinphoneChatRoom * _linphone_core_create_chat_room_from_url(LinphoneCore *lc, const char *to) { + LinphoneAddress *parsed_url = NULL; + if ((parsed_url = linphone_core_interpret_url(lc, to)) != NULL) { + return _linphone_core_create_chat_room(lc, parsed_url); } return NULL; } -bool_t linphone_chat_room_matches(LinphoneChatRoom *cr, const LinphoneAddress *from){ - return linphone_address_weak_equal(cr->peer_url,from); +LinphoneChatRoom * _linphone_core_get_chat_room(LinphoneCore *lc, const LinphoneAddress *addr){ + LinphoneChatRoom *cr=NULL; + MSList *elem; + for(elem=lc->chatrooms;elem!=NULL;elem=ms_list_next(elem)){ + cr=(LinphoneChatRoom*)elem->data; + if (linphone_chat_room_matches(cr,addr)){ + break; + } + cr=NULL; + } + return cr; } -/** - * Create a new chat room for messaging from a sip uri like sip:joe@sip.linphone.org if not already existing, else return exisiting one - * @param lc #LinphoneCore object - * @param to destination address for messages - * @return #LinphoneChatRoom where messaging can take place. - */ -LinphoneChatRoom* linphone_core_get_or_create_chat_room(LinphoneCore* lc, const char* to) { +static LinphoneChatRoom * _linphone_core_get_or_create_chat_room(LinphoneCore* lc, const char* to) { LinphoneAddress *to_addr=linphone_core_interpret_url(lc,to); LinphoneChatRoom *ret; @@ -331,17 +355,64 @@ LinphoneChatRoom* linphone_core_get_or_create_chat_room(LinphoneCore* lc, const ms_error("linphone_core_get_or_create_chat_room(): Cannot make a valid address with %s",to); return NULL; } - ret=linphone_core_get_chat_room(lc,to_addr); + ret=_linphone_core_get_chat_room(lc,to_addr); linphone_address_destroy(to_addr); if (!ret){ - ret=linphone_core_create_chat_room(lc,to); + ret=_linphone_core_create_chat_room_from_url(lc,to); } return ret; } +/** + * Create a new chat room for messaging from a sip uri like sip:joe@sip.linphone.org if not already existing, else return exisiting one + * @param lc #LinphoneCore object + * @param to destination address for messages + * @return #LinphoneChatRoom where messaging can take place. + * @deprecated Use linphone_core_get_chat_room() or linphone_core_get_chat_room_from_uri() instead. + */ +LinphoneChatRoom* linphone_core_get_or_create_chat_room(LinphoneCore* lc, const char* to) { + return _linphone_core_get_or_create_chat_room(lc, to); +} + +/** + * Create a new chat room for messaging from a sip uri like sip:joe@sip.linphone.org + * @param lc #LinphoneCore object + * @param to destination address for messages + * @return #LinphoneChatRoom where messaging can take place. + * @deprecated Use linphone_core_get_chat_room() or linphone_core_get_chat_room_from_uri() instead. + */ +LinphoneChatRoom * linphone_core_create_chat_room(LinphoneCore *lc, const char *to) { + return _linphone_core_get_or_create_chat_room(lc, to); +} + +/** + * Get a chat room whose peer is the supplied address. If it does not exist yet, it will be created. + * @param lc the linphone core + * @param addr a linphone address. + * @returns #LinphoneChatRoom where messaging can take place. +**/ +LinphoneChatRoom *linphone_core_get_chat_room(LinphoneCore *lc, const LinphoneAddress *addr){ + LinphoneChatRoom *ret = _linphone_core_get_chat_room(lc, addr); + if (!ret) { + ret = _linphone_core_create_chat_room(lc, linphone_address_clone(addr)); + } + return ret; +} + +/** + * Get a chat room for messaging from a sip uri like sip:joe@sip.linphone.org. If it does not exist yet, it will be created. + * @param lc The linphone core + * @param to The destination address for messages. + * @returns #LinphoneChatRoom where messaging can take place. +**/ +LinphoneChatRoom * linphone_core_get_chat_room_from_uri(LinphoneCore *lc, const char *to) { + return _linphone_core_get_or_create_chat_room(lc, to); +} + static void linphone_chat_room_delete_composing_idle_timer(LinphoneChatRoom *cr) { if (cr->composing_idle_timer) { - sal_cancel_timer(cr->lc->sal, cr->composing_idle_timer); + if(cr->lc->sal) + sal_cancel_timer(cr->lc->sal, cr->composing_idle_timer); belle_sip_object_unref(cr->composing_idle_timer); cr->composing_idle_timer = NULL; } @@ -349,7 +420,8 @@ static void linphone_chat_room_delete_composing_idle_timer(LinphoneChatRoom *cr) static void linphone_chat_room_delete_composing_refresh_timer(LinphoneChatRoom *cr) { if (cr->composing_refresh_timer) { - sal_cancel_timer(cr->lc->sal, cr->composing_refresh_timer); + if(cr->lc->sal) + sal_cancel_timer(cr->lc->sal, cr->composing_refresh_timer); belle_sip_object_unref(cr->composing_refresh_timer); cr->composing_refresh_timer = NULL; } @@ -357,28 +429,55 @@ static void linphone_chat_room_delete_composing_refresh_timer(LinphoneChatRoom * static void linphone_chat_room_delete_remote_composing_refresh_timer(LinphoneChatRoom *cr) { if (cr->remote_composing_refresh_timer) { - sal_cancel_timer(cr->lc->sal, cr->remote_composing_refresh_timer); + if(cr->lc->sal) + sal_cancel_timer(cr->lc->sal, cr->remote_composing_refresh_timer); belle_sip_object_unref(cr->remote_composing_refresh_timer); cr->remote_composing_refresh_timer = NULL; } } -/** - * Destroy a LinphoneChatRoom. - * @param cr #LinphoneChatRoom object - */ -void linphone_chat_room_destroy(LinphoneChatRoom *cr){ - LinphoneCore *lc=cr->lc; +static void _linphone_chat_room_destroy(LinphoneChatRoom *cr){ ms_list_free_with_data(cr->transient_messages, (void (*)(void*))linphone_chat_message_unref); linphone_chat_room_delete_composing_idle_timer(cr); linphone_chat_room_delete_composing_refresh_timer(cr); linphone_chat_room_delete_remote_composing_refresh_timer(cr); - lc->chatrooms=ms_list_remove(lc->chatrooms,(void *) cr); + if (cr->lc != NULL) { + cr->lc->chatrooms=ms_list_remove(cr->lc->chatrooms,(void *) cr); + } linphone_address_destroy(cr->peer_url); ms_free(cr->peer); - ms_free(cr); } +/** + * Destroy a LinphoneChatRoom. + * @param cr #LinphoneChatRoom object + * @deprecated Use linphone_chat_room_unref() instead. + */ +void linphone_chat_room_destroy(LinphoneChatRoom *cr) { + linphone_chat_room_unref(cr); +} + +void linphone_chat_room_release(LinphoneChatRoom *cr) { + cr->lc = NULL; + linphone_chat_room_unref(cr); +} + +LinphoneChatRoom * linphone_chat_room_ref(LinphoneChatRoom *cr) { + belle_sip_object_ref(cr); + return cr; +} + +void linphone_chat_room_unref(LinphoneChatRoom *cr) { + belle_sip_object_unref(cr); +} + +void * linphone_chat_room_get_user_data(const LinphoneChatRoom *cr) { + return cr->user_data; +} + +void linphone_chat_room_set_user_data(LinphoneChatRoom *cr, void *ud) { + cr->user_data = ud; +} static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage* msg){ @@ -389,7 +488,7 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatM time_t t=time(NULL); linphone_chat_message_ref(msg); /* Check if we shall upload a file to a server */ - if (msg->file_transfer_information != NULL) { + if (msg->file_transfer_information != NULL && msg->content_type == NULL) { /* open a transaction with the server and send an empty request(RCS5.1 section 3.5.4.8.3.1) */ belle_http_request_listener_callbacks_t cbs={0}; belle_http_request_listener_t *l; @@ -404,9 +503,10 @@ static void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatM NULL, NULL); cbs.process_response=linphone_chat_message_process_response_from_post_file; - cbs.process_io_error=process_io_error; - cbs.process_auth_requested=process_auth_requested; + cbs.process_io_error=process_io_error_upload; + cbs.process_auth_requested=process_auth_requested_upload; l=belle_http_request_listener_create_from_callbacks(&cbs,msg); /* give msg to listener to be able to start the actual file upload when server answer a 204 No content */ + msg->http_request = req; /* keep a reference on the request to be able to cancel it */ belle_http_provider_send_request(cr->lc->http_provider,req,l); linphone_chat_message_unref(msg); return; @@ -487,31 +587,10 @@ void linphone_chat_room_send_message(LinphoneChatRoom *cr, const char *msg) { void linphone_chat_room_message_received(LinphoneChatRoom *cr, LinphoneCore *lc, LinphoneChatMessage *msg){ if (msg->message) //legacy API - if (lc->vtable.text_received!=NULL) lc->vtable.text_received(lc, cr, msg->from, msg->message); - if (lc->vtable.message_received!=NULL) lc->vtable.message_received(lc, cr,msg); - if (cr->lc->vtable.is_composing_received != NULL) { - cr->remote_is_composing = LinphoneIsComposingIdle; - cr->lc->vtable.is_composing_received(cr->lc, cr); - } -} - -/** - * Retrieve an existing chat room whose peer is the supplied address, if exists. - * @param lc the linphone core - * @param addr a linphone address. - * @returns the matching chatroom, or NULL if no such chatroom exists. -**/ -LinphoneChatRoom *linphone_core_get_chat_room(LinphoneCore *lc, const LinphoneAddress *addr){ - LinphoneChatRoom *cr=NULL; - MSList *elem; - for(elem=lc->chatrooms;elem!=NULL;elem=ms_list_next(elem)){ - cr=(LinphoneChatRoom*)elem->data; - if (linphone_chat_room_matches(cr,addr)){ - break; - } - cr=NULL; - } - return cr; + linphone_core_notify_text_message_received(lc, cr, msg->from, msg->message); + linphone_core_notify_message_received(lc, cr,msg); + cr->remote_is_composing = LinphoneIsComposingIdle; + linphone_core_notify_is_composing_received(cr->lc, cr); } void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessage *sal_msg){ @@ -529,8 +608,7 @@ void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessag /* create a new chat room */ cr=linphone_core_create_chat_room(lc,cleanfrom); } - - if (sal_msg->content_type != NULL) { /* content_type field is, for now, used only for rcs file transfer bu twe shall strcmp it with "application/vnd.gsma.rcs-ft-http+xml" */ + if (sal_msg->content_type != NULL) { /* content_type field is, for now, used only for rcs file transfer but we shall strcmp it with "application/vnd.gsma.rcs-ft-http+xml" */ xmlChar *file_url = NULL; xmlDocPtr xmlMessageBody; xmlNodePtr cur; @@ -623,6 +701,7 @@ void linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessag linphone_address_destroy(addr); msg->storage_id=linphone_chat_message_store(msg); linphone_chat_room_message_received(cr,lc,msg); + linphone_chat_message_unref(msg); ms_free(cleanfrom); } @@ -631,8 +710,7 @@ static int linphone_chat_room_remote_refresh_composing_expired(void *data, unsig belle_sip_object_unref(cr->remote_composing_refresh_timer); cr->remote_composing_refresh_timer = NULL; cr->remote_is_composing = LinphoneIsComposingIdle; - if (cr->lc->vtable.is_composing_received != NULL) - cr->lc->vtable.is_composing_received(cr->lc, cr); + linphone_core_notify_is_composing_received(cr->lc, cr); return BELLE_SIP_STOP; } @@ -677,8 +755,7 @@ static void process_im_is_composing_notification(LinphoneChatRoom *cr, xmlparsin } cr->remote_is_composing = state; - if (cr->lc->vtable.is_composing_received != NULL) - cr->lc->vtable.is_composing_received(cr->lc, cr); + linphone_core_notify_is_composing_received(cr->lc, cr); } } @@ -720,20 +797,6 @@ LinphoneCore* linphone_chat_room_get_core(LinphoneChatRoom *cr){ return cr->lc; } -/** - * Assign a user pointer to the chat room. -**/ -void linphone_chat_room_set_user_data(LinphoneChatRoom *cr, void * ud){ - cr->user_data=ud; -} - -/** - * Retrieve the user pointer associated with the chat room. -**/ -void * linphone_chat_room_get_user_data(LinphoneChatRoom *cr){ - return cr->user_data; -} - /** * get peer address \link linphone_core_create_chat_room() associated to \endlink this #LinphoneChatRoom * @param cr #LinphoneChatRoom object @@ -756,6 +819,7 @@ LinphoneChatMessage* linphone_chat_room_create_message(LinphoneChatRoom *cr, con msg->is_read=TRUE; msg->content_type = NULL; /* this property is used only when transfering file */ msg->file_transfer_information = NULL; /* this property is used only when transfering file */ + msg->http_request = NULL; return msg; } @@ -945,6 +1009,7 @@ const char* linphone_chat_message_state_to_string(const LinphoneChatMessageState case LinphoneChatMessageStateInProgress:return "LinphoneChatMessageStateInProgress"; case LinphoneChatMessageStateDelivered:return "LinphoneChatMessageStateDelivered"; case LinphoneChatMessageStateNotDelivered:return "LinphoneChatMessageStateNotDelivered"; + case LinphoneChatMessageStateFileTransferError:return "LinphoneChatMessageStateFileTransferError"; default: return "Unknown state"; } @@ -1047,22 +1112,22 @@ static void on_recv_body(belle_sip_user_body_handler_t *bh, belle_sip_message_t } LinphoneChatMessage* chatMsg=(LinphoneChatMessage *)data; LinphoneCore *lc = chatMsg->chat_room->lc; + /* TODO: while belle sip doesn't implement the cancel http request method, test if a request is still linked to the message before forwarding the data to callback */ + if (chatMsg->http_request == NULL) { + return; if (chatMsg->file_transfer_information->key != NULL) { /* we have a key, we must decrypt the file */ /* get data from callback to a plainBuffer */ char *plainBuffer = (char *)malloc(size); lime_decryptFile(&(chatMsg->file_transfer_information->cryptoContext), chatMsg->file_transfer_information->key, size, plainBuffer, (char *)buffer); /* call back given by application level */ - if (lc->vtable.file_transfer_received != NULL) { - lc->vtable.file_transfer_received(lc, chatMsg, chatMsg->file_transfer_information, plainBuffer, size); - } + linphone_core_notify_file_transfer_rec(lc, chatMsg, chatMsg->file_transfer_information, plainBuffer, size); free(plainBuffer); } else { /* regular file, no deciphering */ /* call back given by application level */ - if (lc->vtable.file_transfer_received != NULL) { - lc->vtable.file_transfer_received(lc, chatMsg, chatMsg->file_transfer_information, (char *)buffer, size); - } + linphone_core_notify_file_transfer_recd(lc, chatMsg, chatMsg->file_transfer_information, (char *)buffer, size); } + return; } @@ -1131,9 +1196,7 @@ static void linphone_chat_process_response_from_get_file(void *data, const belle lime_decryptFile(&(chatMsg->file_transfer_information->cryptoContext), NULL, 0, NULL, NULL); } /* file downloaded succesfully, call again the callback with size at zero */ - if (lc->vtable.file_transfer_received != NULL) { - lc->vtable.file_transfer_received(lc, chatMsg, chatMsg->file_transfer_information, NULL, 0); - } + linphone_core_notify_file_transfer_recv(lc, chatMsg, chatMsg->file_transfer_information, NULL, 0); } } } @@ -1142,8 +1205,9 @@ static void linphone_chat_process_response_from_get_file(void *data, const belle * Start the download of the file from remote server * * @param message #LinphoneChatMessage + * @param status_cb LinphoneChatMessageStateChangeCb status callback invoked when file is downloaded or could not be downloaded */ -void linphone_chat_message_start_file_download(const LinphoneChatMessage *message) { +void linphone_chat_message_start_file_download(LinphoneChatMessage *message, LinphoneChatMessageStateChangedCb status_cb) { belle_http_request_listener_callbacks_t cbs={0}; belle_http_request_listener_t *l; belle_generic_uri_t *uri; @@ -1162,47 +1226,66 @@ void linphone_chat_message_start_file_download(const LinphoneChatMessage *messag cbs.process_response_headers=linphone_chat_process_response_headers_from_get_file; cbs.process_response=linphone_chat_process_response_from_get_file; - cbs.process_io_error=process_io_error; - cbs.process_auth_requested=process_auth_requested; + cbs.process_io_error=process_io_error_download; + cbs.process_auth_requested=process_auth_requested_download; l=belle_http_request_listener_create_from_callbacks(&cbs, (void *)message); belle_sip_object_data_set(BELLE_SIP_OBJECT(req),"message",(void *)message,NULL); + message->http_request = req; /* keep a reference on the request to be able to cancel the download */ + message->cb = status_cb; + message->state = LinphoneChatMessageStateInProgress; /* start the download, status is In Progress */ belle_http_provider_send_request(message->chat_room->lc->http_provider,req,l); } + +/** + * Cancel an ongoing file transfer attached to this message.(upload or download) + * @param msg #LinphoneChatMessage + */ +void linphone_chat_room_cancel_file_transfer(LinphoneChatMessage *msg) { + ms_message("Cancelled file transfer %s - msg [%p] chat room[%p]", (msg->external_body_url==NULL)?msg->chat_room->lc->file_transfer_server:msg->external_body_url, msg, msg->chat_room); + /* TODO: here we shall call the cancel http request from bellesip API when it is available passing msg->http_request */ + /* waiting for this API, just set to NULL the reference to the request in the message and any request */ + msg->http_request = NULL; + if (msg->cb) { + msg->cb(msg, LinphoneChatMessageStateNotDelivered, msg->chat_room->lc); + } +} + + /** * Set origin of the message - *@param message #LinphoneChatMessage obj - *@param from #LinphoneAddress origin of this message (copied) + * @param[in] message #LinphoneChatMessage obj + * @param[in] from #LinphoneAddress origin of this message (copied) */ -void linphone_chat_message_set_from(LinphoneChatMessage* message, const LinphoneAddress* from) { +void linphone_chat_message_set_from_address(LinphoneChatMessage* message, const LinphoneAddress* from) { if(message->from) linphone_address_destroy(message->from); message->from=linphone_address_clone(from); } /** * Get origin of the message - *@param message #LinphoneChatMessage obj - *@return #LinphoneAddress + * @param[in] message #LinphoneChatMessage obj + * @return #LinphoneAddress */ -const LinphoneAddress* linphone_chat_message_get_from(const LinphoneChatMessage* message) { +const LinphoneAddress* linphone_chat_message_get_from_address(const LinphoneChatMessage* message) { return message->from; } /** * Set destination of the message - *@param message #LinphoneChatMessage obj - *@param to #LinphoneAddress destination of this message (copied) + * @param[in] message #LinphoneChatMessage obj + * @param[in] to #LinphoneAddress destination of this message (copied) */ -void linphone_chat_message_set_to(LinphoneChatMessage* message, const LinphoneAddress* to) { +void linphone_chat_message_set_to_address(LinphoneChatMessage* message, const LinphoneAddress* to) { if(message->to) linphone_address_destroy(message->to); message->to=linphone_address_clone(to); } /** * Get destination of the message - *@param message #LinphoneChatMessage obj - *@return #LinphoneAddress + * @param[in] message #LinphoneChatMessage obj + * @return #LinphoneAddress */ -const LinphoneAddress* linphone_chat_message_get_to(const LinphoneChatMessage* message){ +const LinphoneAddress* linphone_chat_message_get_to_address(const LinphoneChatMessage* message){ if (message->to) return message->to; if (message->dir==LinphoneChatMessageOutgoing){ return message->chat_room->peer_url; @@ -1341,6 +1424,7 @@ static void _linphone_chat_message_destroy(LinphoneChatMessage* msg) { linphone_content_uninit(msg->file_transfer_information); ms_free(msg->file_transfer_information); } + ms_message("LinphoneChatMessage [%p] destroyed.",msg); } @@ -1395,11 +1479,10 @@ LinphoneChatMessage* linphone_chat_room_create_file_transfer_message(LinphoneCha linphone_chat_message_set_to(msg, linphone_chat_room_get_peer_address(cr)); linphone_chat_message_set_from(msg, linphone_address_new(linphone_core_get_identity(cr->lc))); msg->content_type=NULL; /* this will be set to application/vnd.gsma.rcs-ft-http+xml when we will transfer the xml reply from server to the peers */ - + msg->http_request=NULL; /* this will store the http request during file upload to the server */ return msg; } + /** * @} */ - - diff --git a/coreapi/conference.c b/coreapi/conference.c index 7bee313dd..f860c33ad 100644 --- a/coreapi/conference.c +++ b/coreapi/conference.c @@ -41,6 +41,7 @@ static void conference_check_init(LinphoneConference *ctx, int samplerate){ MSAudioConferenceParams params; params.samplerate=samplerate; ctx->conf=ms_audio_conference_new(¶ms); + ctx->terminated=FALSE; } } @@ -74,7 +75,7 @@ void linphone_core_conference_check_uninit(LinphoneCore *lc){ if (ctx->conf){ int remote_count=remote_participants_count(ctx); ms_message("conference_check_uninit(): size=%i",linphone_conference_get_size(ctx)); - if (remote_count==1){ + if (remote_count==1 && !ctx->terminated){ convert_conference_to_call(lc); } if (remote_count==0){ @@ -98,7 +99,7 @@ void linphone_call_add_to_conf(LinphoneCall *call, bool_t muted){ LinphoneCore *lc=call->core; LinphoneConference *conf=&lc->conf_ctx; MSAudioEndpoint *ep; - call->params.has_video = FALSE; + call->params->has_video = FALSE; call->camera_enabled = FALSE; ep=ms_audio_endpoint_get_from_stream(call->audiostream,TRUE); ms_audio_conference_add_member(conf->conf,ep); @@ -184,15 +185,15 @@ float linphone_core_get_conference_local_input_volume(LinphoneCore *lc){ int linphone_core_add_to_conference(LinphoneCore *lc, LinphoneCall *call){ LinphoneConference *conf=&lc->conf_ctx; - if (call->current_params.in_conference){ + if (call->current_params->in_conference){ ms_error("Already in conference"); return -1; } conference_check_init(&lc->conf_ctx, lp_config_get_int(lc->config, "sound","conference_rate",16000)); if (call->state==LinphoneCallPaused){ - call->params.in_conference=TRUE; - call->params.has_video=FALSE; + call->params->in_conference=TRUE; + call->params->has_video=FALSE; linphone_core_resume_call(lc,call); }else if (call->state==LinphoneCallStreamsRunning){ LinphoneCallParams *params=linphone_call_params_copy(linphone_call_get_current_params(call)); @@ -222,8 +223,8 @@ static int remove_from_conference(LinphoneCore *lc, LinphoneCall *call, bool_t a int err=0; char *str; - if (!call->current_params.in_conference){ - if (call->params.in_conference){ + if (!call->current_params->in_conference){ + if (call->params->in_conference){ ms_warning("Not (yet) in conference, be patient"); return -1; }else{ @@ -231,7 +232,7 @@ static int remove_from_conference(LinphoneCore *lc, LinphoneCall *call, bool_t a return -1; } } - call->params.in_conference=FALSE; + call->params->in_conference=FALSE; str=linphone_call_get_remote_address_as_string(call); ms_message("%s will be removed from conference", str); @@ -251,7 +252,6 @@ static int remove_from_conference(LinphoneCore *lc, LinphoneCall *call, bool_t a ms_message("Pausing call to actually remove from conference"); err=_linphone_core_pause_call(lc,call); } - return err; } @@ -267,7 +267,7 @@ static int convert_conference_to_call(LinphoneCore *lc){ while (calls) { LinphoneCall *rc=(LinphoneCall*)calls->data; calls=calls->next; - if (rc->params.in_conference) { // not using current_param + if (rc->params->in_conference) { // not using current_param bool_t active_after_removed=linphone_core_is_in_conference(lc); err=remove_from_conference(lc, rc, active_after_removed); break; @@ -370,7 +370,7 @@ int linphone_core_add_all_to_conference(LinphoneCore *lc) { while (calls) { LinphoneCall *call=(LinphoneCall*)calls->data; calls=calls->next; - if (!call->current_params.in_conference) { + if (!call->current_params->in_conference) { linphone_core_add_to_conference(lc, call); } } @@ -388,10 +388,13 @@ int linphone_core_add_all_to_conference(LinphoneCore *lc) { **/ int linphone_core_terminate_conference(LinphoneCore *lc) { MSList *calls=lc->calls; + LinphoneConference *conf=&lc->conf_ctx; + conf->terminated=TRUE; + while (calls) { LinphoneCall *call=(LinphoneCall*)calls->data; calls=calls->next; - if (call->current_params.in_conference) { + if (call->current_params->in_conference) { linphone_core_terminate_call(lc, call); } } diff --git a/coreapi/event.c b/coreapi/event.c index 992d058ab..372e0a953 100644 --- a/coreapi/event.c +++ b/coreapi/event.c @@ -89,13 +89,10 @@ LinphoneEvent *linphone_event_new_with_out_of_dialog_op(LinphoneCore *lc, SalOp } void linphone_event_set_state(LinphoneEvent *lev, LinphoneSubscriptionState state){ - LinphoneCore *lc=lev->lc; if (lev->subscription_state!=state){ ms_message("LinphoneEvent [%p] moving to subscription state %s",lev,linphone_subscription_state_to_string(state)); lev->subscription_state=state; - if (lc->vtable.subscription_state_changed){ - lc->vtable.subscription_state_changed(lev->lc,lev,state); - } + linphone_core_notify_subscription_state_changed(lev->lc,lev,state); if (state==LinphoneSubscriptionTerminated){ linphone_event_unref(lev); } @@ -103,13 +100,10 @@ void linphone_event_set_state(LinphoneEvent *lev, LinphoneSubscriptionState stat } void linphone_event_set_publish_state(LinphoneEvent *lev, LinphonePublishState state){ - LinphoneCore *lc=lev->lc; if (lev->publish_state!=state){ ms_message("LinphoneEvent [%p] moving to publish state %s",lev,linphone_publish_state_to_string(state)); lev->publish_state=state; - if (lc->vtable.publish_state_changed){ - lc->vtable.publish_state_changed(lev->lc,lev,state); - } + linphone_core_notify_publish_state_changed(lev->lc,lev,state); switch(state){ case LinphonePublishCleared: linphone_event_unref(lev); diff --git a/coreapi/friend.c b/coreapi/friend.c index 7b0ddd816..d1ecd560c 100644 --- a/coreapi/friend.c +++ b/coreapi/friend.c @@ -253,8 +253,7 @@ static void linphone_friend_invalidate_subscription(LinphoneFriend *lf){ linphone_presence_model_unref(lf->presence); } lf->presence = linphone_presence_model_new_with_activity(LinphonePresenceActivityOffline,"unknown activity"); - if (lc->vtable.notify_presence_received) - lc->vtable.notify_presence_received(lc,lf); + linphone_core_notify_notify_presence_received(lc,lf); } lf->initial_subscribes_sent=FALSE; } diff --git a/coreapi/gitversion.cmake b/coreapi/gitversion.cmake new file mode 100644 index 000000000..5c6facdab --- /dev/null +++ b/coreapi/gitversion.cmake @@ -0,0 +1,39 @@ +############################################################################ +# CMakeLists.txt +# Copyright (C) 2014 Belledonne Communications, Grenoble France +# +############################################################################ +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################ + +if(GIT_EXECUTABLE) + execute_process( + COMMAND ${GIT_EXECUTABLE} describe --always + WORKING_DIRECTORY ${WORK_DIR} + OUTPUT_VARIABLE GIT_REVISION + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + execute_process( + COMMAND ${CMAKE_COMMAND} -E echo "#define LIBLINPHONE_GIT_VERSION \"${GIT_REVISION}\"" + OUTPUT_FILE ${OUTPUT_DIR}/liblinphone_gitversion.h + ) +else() + execute_process( + COMMAND ${CMAKE_COMMAND} -E echo "#define LIBLINPHONE_GIT_VERSION \"unknown\"" + OUTPUT_FILE ${OUTPUT_DIR}/liblinphone_gitversion.h + ) +endif() diff --git a/coreapi/help/CMakeLists.txt b/coreapi/help/CMakeLists.txt new file mode 100644 index 000000000..af624006e --- /dev/null +++ b/coreapi/help/CMakeLists.txt @@ -0,0 +1,45 @@ +############################################################################ +# CMakeLists.txt +# Copyright (C) 2014 Belledonne Communications, Grenoble France +# +############################################################################ +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################ + +find_package(Doxygen) + +if(DOXYGEN_FOUND) + if(DOXYGEN_DOT_FOUND) + set(top_srcdir ${CMAKE_SOURCE_DIR}) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) + file(GLOB DOC_INPUT_FILES + [^.]*.c + [^.]*.dox + ../[^.]*.h + ../[^.]*.c + ) + add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/doc/html/index.html" + COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile ${DOC_INPUT_FILES} + ) + add_custom_target(doc ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/doc/html/index.html") + install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/doc/html" "${CMAKE_CURRENT_BINARY_DIR}/doc/xml" + DESTINATION "${CMAKE_INSTALL_PREFIX}/share/doc/linphone-${LINPHONE_VERSION}") + else() + message(WARNING "The dot program is needed to generate the linphone documentation. You can get it from http://www.graphviz.org/.") + endif() +endif() diff --git a/coreapi/help/Doxyfile.in b/coreapi/help/Doxyfile.in index 27068c53d..12facea9b 100644 --- a/coreapi/help/Doxyfile.in +++ b/coreapi/help/Doxyfile.in @@ -34,7 +34,7 @@ DETAILS_AT_TOP = NO INHERIT_DOCS = YES DISTRIBUTE_GROUP_DOC = NO TAB_SIZE = 8 -ALIASES = +ALIASES = mslist{1}="A list of \ref \1 objects. \xmlonly \1 \endxmlonly" OPTIMIZE_OUTPUT_FOR_C = YES OPTIMIZE_OUTPUT_JAVA = NO SUBGROUPING = YES diff --git a/coreapi/help/Makefile.am b/coreapi/help/Makefile.am index 84822e51c..479d2b31d 100644 --- a/coreapi/help/Makefile.am +++ b/coreapi/help/Makefile.am @@ -1,7 +1,7 @@ EXTRA_DIST=Doxyfile.in doxygen.dox -SOURCES=doxygen.dox $(top_srcdir)/coreapi/help/*.c $(top_srcdir)/coreapi/*.c $(top_srcdir)/coreapi/*.h +SOURCES=doxygen.dox $(top_srcdir)/coreapi/help/*.c $(top_srcdir)/coreapi/*.c $(top_srcdir)/coreapi/*.h # html doc @@ -84,6 +84,7 @@ filetransfer_LDADD=$(helloworld_LDADD) AM_CFLAGS=\ -I$(top_srcdir)/coreapi \ $(STRICT_OPTIONS) \ + $(STRICT_OPTIONS_CC) \ -DIN_LINPHONE \ $(ORTP_CFLAGS) \ $(MEDIASTREAMER_CFLAGS) \ @@ -98,4 +99,4 @@ AM_CFLAGS=\ tutodir=$(datadir)/tutorials/linphone tuto_DATA=$(LINPHONE_TUTOS) -endif +endif diff --git a/coreapi/help/buddy_status.c b/coreapi/help/buddy_status.c index 40db6458e..cd7f13d52 100644 --- a/coreapi/help/buddy_status.c +++ b/coreapi/help/buddy_status.c @@ -1,7 +1,7 @@ /* buddy_status -Copyright (C) 2010 Belledonne Communications SARL +Copyright (C) 2010 Belledonne Communications SARL This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -73,7 +73,7 @@ static void new_subscription_requested (LinphoneCore *lc, LinphoneFriend *frien * Registration state notification callback */ static void registration_state_changed(struct _LinphoneCore *lc, LinphoneProxyConfig *cfg, LinphoneRegistrationState cstate, const char *message){ - printf("New registration state %s for user id [%s] at proxy [%s]\n" + printf("New registration state %s for user id [%s] at proxy [%s]" ,linphone_registration_state_to_string(cstate) ,linphone_proxy_config_get_identity(cfg) ,linphone_proxy_config_get_addr(cfg)); @@ -87,6 +87,8 @@ int main(int argc, char *argv[]){ char* identity=NULL; char* password=NULL; + LinphoneFriend* my_friend=NULL; + /* takes sip uri identity from the command line arguments */ if (argc>1){ dest_friend=argv[1]; @@ -104,7 +106,7 @@ int main(int argc, char *argv[]){ #ifdef DEBUG linphone_core_enable_logs(NULL); /*enable liblinphone logs.*/ #endif - /* + /* Fill the LinphoneCoreVTable with application callbacks. All are optional. Here we only use the both notify_presence_received and new_subscription_requested callbacks in order to get notifications about friend status. @@ -123,11 +125,11 @@ int main(int argc, char *argv[]){ LinphoneProxyConfig* proxy_cfg = linphone_proxy_config_new(); /*parse identity*/ LinphoneAddress *from = linphone_address_new(identity); + LinphoneAuthInfo *info; if (from==NULL){ printf("%s not a valid sip uri, must be like sip:toto@sip.linphone.org \n",identity); goto end; } - LinphoneAuthInfo *info; if (password!=NULL){ info=linphone_auth_info_new(linphone_address_get_username(from),NULL,password,NULL,NULL,NULL); /*create authentication structure from identity*/ linphone_core_add_auth_info(lc,info); /*add authentication info to LinphoneCore*/ @@ -152,7 +154,6 @@ int main(int argc, char *argv[]){ while( running && linphone_proxy_config_get_state(proxy_cfg) == LinphoneRegistrationProgress); } - LinphoneFriend* my_friend=NULL; if (dest_friend) { my_friend = linphone_friend_new_with_address(dest_friend); /*creates friend object from dest*/ diff --git a/coreapi/help/chatroom.c b/coreapi/help/chatroom.c index 51fc4a237..1f0f200a0 100644 --- a/coreapi/help/chatroom.c +++ b/coreapi/help/chatroom.c @@ -1,7 +1,7 @@ /* linphone -Copyright (C) 2010 Belledonne Communications SARL +Copyright (C) 2010 Belledonne Communications SARL This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -55,7 +55,7 @@ int main(int argc, char *argv[]){ LinphoneCoreVTable vtable={0}; char* dest_friend=NULL; - + LinphoneChatRoom* chat_room; /* takes sip uri identity from the command line arguments */ if (argc>1){ @@ -67,7 +67,7 @@ int main(int argc, char *argv[]){ #ifdef DEBUG linphone_core_enable_logs(NULL); /*enable liblinphone logs.*/ #endif - /* + /* Fill the LinphoneCoreVTable with application callbacks. All are optional. Here we only use the text_received callback in order to get notifications about incoming message. @@ -81,7 +81,7 @@ int main(int argc, char *argv[]){ /*Next step is to create a chat root*/ - LinphoneChatRoom* chat_room = linphone_core_create_chat_room(lc,dest_friend); + chat_room = linphone_core_create_chat_room(lc,dest_friend); linphone_chat_room_send_message(chat_room,"Hello world"); /*sending message*/ diff --git a/coreapi/help/filetransfer.c b/coreapi/help/filetransfer.c index 3005fff01..7cfc2cca9 100644 --- a/coreapi/help/filetransfer.c +++ b/coreapi/help/filetransfer.c @@ -1,7 +1,7 @@ /* linphone -Copyright (C) 2010 Belledonne Communications SARL +Copyright (C) 2010 Belledonne Communications SARL This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -114,16 +114,6 @@ static void file_transfer_send(LinphoneCore *lc, LinphoneChatMessage *message, } -/* - * Call back called when a message is received - */ -static void message_received(LinphoneCore *lc, LinphoneChatRoom *cr, LinphoneChatMessage *msg) { - const LinphoneContent *file_transfer_info = linphone_chat_message_get_file_transfer_information(msg); - printf ("Do you really want to download %s (size %ld)?[Y/n]\nOk, let's go\n", file_transfer_info->name, (long int)file_transfer_info->size); - - linphone_chat_message_start_file_download(msg); - -} /* * Call back to get delivery status of a message * */ @@ -135,6 +125,16 @@ static void linphone_file_transfer_state_changed(LinphoneChatMessage* msg,Linpho free(to); } +/* + * Call back called when a message is received + */ +static void message_received(LinphoneCore *lc, LinphoneChatRoom *cr, LinphoneChatMessage *msg) { + const LinphoneContent *file_transfer_info = linphone_chat_message_get_file_transfer_information(msg); + printf ("Do you really want to download %s (size %ld)?[Y/n]\nOk, let's go\n", file_transfer_info->name, (long int)file_transfer_info->size); + + linphone_chat_message_start_file_download(msg, linphone_file_transfer_state_changed); + +} LinphoneCore *lc; int main(int argc, char *argv[]){ @@ -143,6 +143,10 @@ int main(int argc, char *argv[]){ const char* dest_friend=NULL; int i; const char* big_file_content="big file"; + LinphoneChatRoom* chat_room; + LinphoneContent content; + LinphoneChatMessage* chat_message; + /*seting dummy file content to something*/ for (i=0;i1){ @@ -105,7 +109,7 @@ int main(int argc, char *argv[]){ #ifdef DEBUG linphone_core_enable_logs(NULL); /*enable liblinphone logs.*/ #endif - /* + /* Fill the LinphoneCoreVTable with application callbacks. All are optional. Here we only use the registration_state_changed callbacks in order to get notifications about the progress of the registration. @@ -118,30 +122,28 @@ int main(int argc, char *argv[]){ */ lc=linphone_core_new(&vtable,NULL,NULL,data); - LinphoneProxyConfig* proxy_cfg; /*create proxy config*/ proxy_cfg = linphone_proxy_config_new(); /*parse identity*/ - LinphoneAddress *from = linphone_address_new(identity); + from = linphone_address_new(identity); if (from==NULL){ printf("%s not a valid sip uri, must be like sip:toto@sip.linphone.org \n",identity); goto end; } - LinphoneAuthInfo *info; - if (password!=NULL){ - info=linphone_auth_info_new(linphone_address_get_username(from),NULL,password,NULL,NULL,NULL); /*create authentication structure from identity*/ - linphone_core_add_auth_info(lc,info); /*add authentication info to LinphoneCore*/ - } + if (password!=NULL){ + info=linphone_auth_info_new(linphone_address_get_username(from),NULL,password,NULL,NULL,NULL); /*create authentication structure from identity*/ + linphone_core_add_auth_info(lc,info); /*add authentication info to LinphoneCore*/ + } - // configure proxy entries - linphone_proxy_config_set_identity(proxy_cfg,identity); /*set identity with user name and domain*/ - const char* server_addr = linphone_address_get_domain(from); /*extract domain address from identity*/ - linphone_proxy_config_set_server_addr(proxy_cfg,server_addr); /* we assume domain = proxy server address*/ - linphone_proxy_config_enable_register(proxy_cfg,TRUE); /*activate registration for this proxy config*/ - linphone_address_destroy(from); /*release resource*/ + // configure proxy entries + linphone_proxy_config_set_identity(proxy_cfg,identity); /*set identity with user name and domain*/ + server_addr = linphone_address_get_domain(from); /*extract domain address from identity*/ + linphone_proxy_config_set_server_addr(proxy_cfg,server_addr); /* we assume domain = proxy server address*/ + linphone_proxy_config_enable_register(proxy_cfg,TRUE); /*activate registration for this proxy config*/ + linphone_address_destroy(from); /*release resource*/ - linphone_core_add_proxy_config(lc,proxy_cfg); /*add proxy config to linphone core*/ - linphone_core_set_default_proxy(lc,proxy_cfg); /*set to default proxy*/ + linphone_core_add_proxy_config(lc,proxy_cfg); /*add proxy config to linphone core*/ + linphone_core_set_default_proxy(lc,proxy_cfg); /*set to default proxy*/ i=0; /* main loop for receiving notifications and doing background linphonecore work: */ @@ -163,7 +165,7 @@ int main(int argc, char *argv[]){ linphone_proxy_config_edit(proxy_cfg); /*start editing proxy configuration*/ linphone_proxy_config_enable_register(proxy_cfg,FALSE); /*de-activate registration for this proxy config*/ linphone_proxy_config_done(proxy_cfg); /*initiate REGISTER with expire = 0*/ - + if (data->ev){ linphone_event_terminate(data->ev); } diff --git a/coreapi/help/registration.c b/coreapi/help/registration.c index 70ab4f4ca..8dbab6440 100644 --- a/coreapi/help/registration.c +++ b/coreapi/help/registration.c @@ -1,7 +1,7 @@ /* linphone -Copyright (C) 2010 Belledonne Communications SARL +Copyright (C) 2010 Belledonne Communications SARL This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -60,9 +60,13 @@ static void registration_state_changed(struct _LinphoneCore *lc, LinphoneProxyCo LinphoneCore *lc; int main(int argc, char *argv[]){ LinphoneCoreVTable vtable={0}; + LinphoneProxyConfig* proxy_cfg; + LinphoneAddress *from; + LinphoneAuthInfo *info; char* identity=NULL; char* password=NULL; + const char* server_addr; /* takes sip uri identity from the command line arguments */ if (argc>1){ @@ -79,7 +83,7 @@ int main(int argc, char *argv[]){ #ifdef DEBUG linphone_core_enable_logs(NULL); /*enable liblinphone logs.*/ #endif - /* + /* Fill the LinphoneCoreVTable with application callbacks. All are optional. Here we only use the registration_state_changed callbacks in order to get notifications about the progress of the registration. @@ -91,30 +95,28 @@ int main(int argc, char *argv[]){ */ lc=linphone_core_new(&vtable,NULL,NULL,NULL); - LinphoneProxyConfig* proxy_cfg; /*create proxy config*/ proxy_cfg = linphone_proxy_config_new(); /*parse identity*/ - LinphoneAddress *from = linphone_address_new(identity); + from = linphone_address_new(identity); if (from==NULL){ printf("%s not a valid sip uri, must be like sip:toto@sip.linphone.org \n",identity); goto end; } - LinphoneAuthInfo *info; - if (password!=NULL){ - info=linphone_auth_info_new(linphone_address_get_username(from),NULL,password,NULL,NULL,NULL); /*create authentication structure from identity*/ - linphone_core_add_auth_info(lc,info); /*add authentication info to LinphoneCore*/ - } + if (password!=NULL){ + info=linphone_auth_info_new(linphone_address_get_username(from),NULL,password,NULL,NULL,NULL); /*create authentication structure from identity*/ + linphone_core_add_auth_info(lc,info); /*add authentication info to LinphoneCore*/ + } - // configure proxy entries - linphone_proxy_config_set_identity(proxy_cfg,identity); /*set identity with user name and domain*/ - const char* server_addr = linphone_address_get_domain(from); /*extract domain address from identity*/ - linphone_proxy_config_set_server_addr(proxy_cfg,server_addr); /* we assume domain = proxy server address*/ - linphone_proxy_config_enable_register(proxy_cfg,TRUE); /*activate registration for this proxy config*/ - linphone_address_destroy(from); /*release resource*/ + // configure proxy entries + linphone_proxy_config_set_identity(proxy_cfg,identity); /*set identity with user name and domain*/ + server_addr = linphone_address_get_domain(from); /*extract domain address from identity*/ + linphone_proxy_config_set_server_addr(proxy_cfg,server_addr); /* we assume domain = proxy server address*/ + linphone_proxy_config_enable_register(proxy_cfg,TRUE); /*activate registration for this proxy config*/ + linphone_address_destroy(from); /*release resource*/ - linphone_core_add_proxy_config(lc,proxy_cfg); /*add proxy config to linphone core*/ - linphone_core_set_default_proxy(lc,proxy_cfg); /*set to default proxy*/ + linphone_core_add_proxy_config(lc,proxy_cfg); /*add proxy config to linphone core*/ + linphone_core_set_default_proxy(lc,proxy_cfg); /*set to default proxy*/ /* main loop for receiving notifications and doing background linphonecore work: */ diff --git a/coreapi/info.c b/coreapi/info.c index 4279a963c..ca078f29c 100644 --- a/coreapi/info.c +++ b/coreapi/info.c @@ -205,8 +205,7 @@ void linphone_core_notify_info_message(LinphoneCore* lc,SalOp *op, const SalBody LinphoneInfoMessage *info=ms_new0(LinphoneInfoMessage,1); info->headers=sal_custom_header_clone(sal_op_get_recv_custom_header(op)); if (body) linphone_content_copy_from_sal_body(&info->content,body); - if (lc->vtable.info_received) - lc->vtable.info_received(lc,call,info); + linphone_core_notify_info_received(lc,call,info); linphone_info_message_destroy(info); } } diff --git a/coreapi/ldap/ldapprovider.c b/coreapi/ldap/ldapprovider.c index f9a4add67..75b6b19a1 100644 --- a/coreapi/ldap/ldapprovider.c +++ b/coreapi/ldap/ldapprovider.c @@ -567,10 +567,11 @@ LinphoneLDAPContactProvider*linphone_ldap_contact_provider_create(LinphoneCore* belle_sip_object_unref(obj); obj = NULL; } else { + int ret; linphone_dictionary_foreach( config, linphone_ldap_contact_provider_config_dump_cb, 0 ); linphone_ldap_contact_provider_loadconfig(obj, config); - int ret = ldap_initialize(&(obj->ld),obj->server); + ret = ldap_initialize(&(obj->ld),obj->server); if( ret != LDAP_SUCCESS ){ ms_error( "Problem initializing ldap on url '%s': %s", obj->server, ldap_err2string(ret)); @@ -617,9 +618,10 @@ static int linphone_ldap_request_entry_compare_strong(const void*a, const void* static inline LinphoneLDAPContactSearch* linphone_ldap_contact_provider_request_search( LinphoneLDAPContactProvider* obj, int msgid ) { LinphoneLDAPContactSearch dummy = {}; + MSList* list_entry; dummy.msgid = msgid; - MSList* list_entry = ms_list_find_custom(obj->requests, linphone_ldap_request_entry_compare_weak, &dummy); + list_entry = ms_list_find_custom(obj->requests, linphone_ldap_request_entry_compare_weak, &dummy); if( list_entry ) return list_entry->data; else return NULL; } @@ -680,13 +682,14 @@ static LinphoneLDAPContactSearch* linphone_ldap_contact_provider_begin_search ( void* cb_data ) { bool_t connected = obj->connected; + LinphoneLDAPContactSearch* request; // if we're not yet connected, bind if( !connected ) { if( !obj->bind_thread ) linphone_ldap_contact_provider_bind(obj); } - LinphoneLDAPContactSearch* request = linphone_ldap_contact_search_create( obj, predicate, cb, cb_data ); + request = linphone_ldap_contact_search_create( obj, predicate, cb, cb_data ); if( connected ){ int ret = linphone_ldap_contact_provider_perform_search(obj, request); @@ -711,6 +714,7 @@ static LinphoneLDAPContactSearch* linphone_ldap_contact_provider_begin_search ( static int linphone_ldap_contact_provider_marshal(LinphoneLDAPContactProvider* obj, char* buff, size_t buff_size, size_t *offset) { belle_sip_error_code error = BELLE_SIP_OK; + char **attr; error = belle_sip_snprintf(buff, buff_size, offset, "ld:%p,\n", obj->ld); if(error!= BELLE_SIP_OK) return error; @@ -741,7 +745,7 @@ static int linphone_ldap_contact_provider_marshal(LinphoneLDAPContactProvider* o obj->sip_attr, obj->name_attr); if(error!= BELLE_SIP_OK) return error; - char **attr = obj->attributes; + attr = obj->attributes; while( *attr ){ error = belle_sip_snprintf(buff, buff_size, offset, "- %s\n", *attr); if(error!= BELLE_SIP_OK) return error; diff --git a/coreapi/linphone_tunnel.cc b/coreapi/linphone_tunnel.cc index 151755078..8abeb3b05 100644 --- a/coreapi/linphone_tunnel.cc +++ b/coreapi/linphone_tunnel.cc @@ -29,14 +29,18 @@ #include "private.h" #include "lpconfig.h" -LinphoneTunnel* linphone_core_get_tunnel(LinphoneCore *lc){ +static const char *_tunnel_mode_str[3] = { "disable", "enable", "auto" }; + +static LinphoneTunnelMode _string_to_tunnel_mode(const char *string); +static const char *_tunnel_mode_to_string(LinphoneTunnelMode mode); + +LinphoneTunnel* linphone_core_get_tunnel(const LinphoneCore *lc){ return lc->tunnel; } struct _LinphoneTunnel { belledonnecomm::TunnelManager *manager; MSList *config_list; - bool_t auto_detect_enabled; }; extern "C" LinphoneTunnel* linphone_core_tunnel_new(LinphoneCore *lc){ @@ -45,31 +49,37 @@ extern "C" LinphoneTunnel* linphone_core_tunnel_new(LinphoneCore *lc){ return tunnel; } -static inline belledonnecomm::TunnelManager *bcTunnel(LinphoneTunnel *tunnel){ +belledonnecomm::TunnelManager *bcTunnel(const LinphoneTunnel *tunnel){ return tunnel->manager; } -static inline _LpConfig *config(LinphoneTunnel *tunnel){ +static inline _LpConfig *config(const LinphoneTunnel *tunnel){ return tunnel->manager->getLinphoneCore()->config; } void linphone_tunnel_destroy(LinphoneTunnel *tunnel){ delete tunnel->manager; + + ms_list_free_with_data(tunnel->config_list, (void (*)(void *))linphone_tunnel_config_destroy); + ms_free(tunnel); } static char *linphone_tunnel_config_to_string(const LinphoneTunnelConfig *tunnel_config) { char *str = NULL; - if(linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config) != -1) { - str = ms_strdup_printf("%s:%d:%d:%d", - linphone_tunnel_config_get_host(tunnel_config), - linphone_tunnel_config_get_port(tunnel_config), - linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config), - linphone_tunnel_config_get_delay(tunnel_config)); - } else { - str = ms_strdup_printf("%s:%d", - linphone_tunnel_config_get_host(tunnel_config), - linphone_tunnel_config_get_port(tunnel_config)); + const char *host = linphone_tunnel_config_get_host(tunnel_config); + if(host != NULL) { + if(linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config) != -1) { + str = ms_strdup_printf("%s:%d:%d:%d", + linphone_tunnel_config_get_host(tunnel_config), + linphone_tunnel_config_get_port(tunnel_config), + linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config), + linphone_tunnel_config_get_delay(tunnel_config)); + } else { + str = ms_strdup_printf("%s:%d", + linphone_tunnel_config_get_host(tunnel_config), + linphone_tunnel_config_get_port(tunnel_config)); + } } return str; } @@ -97,12 +107,12 @@ static LinphoneTunnelConfig *linphone_tunnel_config_from_string(const char *str) break; case 3: delay = atoi(pch); - break; + break; default: // Abort pos = 0; break; - + } ++pos; pch = strtok(NULL, ":"); @@ -118,26 +128,27 @@ static LinphoneTunnelConfig *linphone_tunnel_config_from_string(const char *str) if(pos == 4) { linphone_tunnel_config_set_delay(tunnel_config, delay); } - ms_free(dstr); + ms_free(dstr); return tunnel_config; } -static void linphone_tunnel_save_config(LinphoneTunnel *tunnel) { - MSList *elem = tunnel->config_list; +static void linphone_tunnel_save_config(const LinphoneTunnel *tunnel) { + MSList *elem = NULL; char *tmp = NULL, *old_tmp = NULL, *tc_str = NULL; - while(elem != NULL) { + for(elem = tunnel->config_list; elem != NULL; elem = elem->next) { LinphoneTunnelConfig *tunnel_config = (LinphoneTunnelConfig *)elem->data; tc_str = linphone_tunnel_config_to_string(tunnel_config); - if(tmp != NULL) { - old_tmp = tmp; - tmp = ms_strdup_printf("%s %s", old_tmp, tc_str); - ms_free(old_tmp); - ms_free(tc_str); - } else { - tmp = tc_str; + if(tc_str != NULL) { + if(tmp != NULL) { + old_tmp = tmp; + tmp = ms_strdup_printf("%s %s", old_tmp, tc_str); + ms_free(old_tmp); + ms_free(tc_str); + } else { + tmp = tc_str; + } } - elem = elem->next; } lp_config_set_string(config(tunnel), "tunnel", "server_addresses", tmp); if(tmp != NULL) { @@ -148,12 +159,12 @@ static void linphone_tunnel_save_config(LinphoneTunnel *tunnel) { static void linphone_tunnel_add_server_intern(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config) { if(linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config) == -1) { - bcTunnel(tunnel)->addServer(linphone_tunnel_config_get_host(tunnel_config), + bcTunnel(tunnel)->addServer(linphone_tunnel_config_get_host(tunnel_config), linphone_tunnel_config_get_port(tunnel_config)); } else { - bcTunnel(tunnel)->addServer(linphone_tunnel_config_get_host(tunnel_config), - linphone_tunnel_config_get_port(tunnel_config), - linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config), + bcTunnel(tunnel)->addServer(linphone_tunnel_config_get_host(tunnel_config), + linphone_tunnel_config_get_port(tunnel_config), + linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config), linphone_tunnel_config_get_delay(tunnel_config)); } tunnel->config_list = ms_list_append(tunnel->config_list, tunnel_config); @@ -205,38 +216,37 @@ void linphone_tunnel_remove_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig MSList *elem = ms_list_find(tunnel->config_list, tunnel_config); if(elem != NULL) { tunnel->config_list = ms_list_remove(tunnel->config_list, tunnel_config); - linphone_tunnel_config_destroy(tunnel_config); + linphone_tunnel_config_destroy(tunnel_config); linphone_tunnel_refresh_config(tunnel); linphone_tunnel_save_config(tunnel); - } + } } -const MSList *linphone_tunnel_get_servers(LinphoneTunnel *tunnel){ +const MSList *linphone_tunnel_get_servers(const LinphoneTunnel *tunnel){ return tunnel->config_list; } void linphone_tunnel_clean_servers(LinphoneTunnel *tunnel){ bcTunnel(tunnel)->cleanServers(); - + /* Free the list */ - ms_list_for_each(tunnel->config_list, (void (*)(void *))linphone_tunnel_config_destroy); - tunnel->config_list = ms_list_free(tunnel->config_list); - + ms_list_free_with_data(tunnel->config_list, (void (*)(void *))linphone_tunnel_config_destroy); + tunnel->config_list = NULL; + linphone_tunnel_save_config(tunnel); } -void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled){ - tunnel->auto_detect_enabled = FALSE; - lp_config_set_int(config(tunnel),"tunnel","enabled",(int)enabled); - bcTunnel(tunnel)->enable(enabled); +void linphone_tunnel_set_mode(LinphoneTunnel *tunnel, LinphoneTunnelMode mode){ + lp_config_set_string(config(tunnel),"tunnel","mode", _tunnel_mode_to_string(mode)); + bcTunnel(tunnel)->setMode(mode); } -bool_t linphone_tunnel_enabled(LinphoneTunnel *tunnel){ - return bcTunnel(tunnel)->isEnabled(); +LinphoneTunnelMode linphone_tunnel_get_mode(const LinphoneTunnel *tunnel){ + return bcTunnel(tunnel)->getMode(); } -bool_t linphone_tunnel_connected(LinphoneTunnel *tunnel){ - return bcTunnel(tunnel)->isReady(); +bool_t linphone_tunnel_connected(const LinphoneTunnel *tunnel){ + return bcTunnel(tunnel)->isConnected(); } static OrtpLogFunc tunnelOrtpLogHandler=NULL; @@ -312,27 +322,65 @@ void linphone_tunnel_reconnect(LinphoneTunnel *tunnel){ bcTunnel(tunnel)->reconnect(); } -void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel){ - tunnel->auto_detect_enabled = TRUE; - bcTunnel(tunnel)->autoDetect(); +void linphone_tunnel_enable_sip(LinphoneTunnel *tunnel, bool_t enable) { + bcTunnel(tunnel)->tunnelizeSipPackets(enable); + lp_config_set_int(config(tunnel), "tunnel", "sip", (enable ? TRUE : FALSE)); } -bool_t linphone_tunnel_auto_detect_enabled(LinphoneTunnel *tunnel) { - return tunnel->auto_detect_enabled; +bool_t linphone_tunnel_sip_enabled(const LinphoneTunnel *tunnel) { + return bcTunnel(tunnel)->tunnelizeSipPacketsEnabled() ? TRUE : FALSE; } static void my_ortp_logv(OrtpLogLevel level, const char *fmt, va_list args){ ortp_logv(level,fmt,args); } +static LinphoneTunnelMode _string_to_tunnel_mode(const char *string) { + if(string != NULL) { + int i; + for(i=0; i<3 && strcmp(string, _tunnel_mode_str[i]) != 0; i++); + if(i<3) { + return (LinphoneTunnelMode)i; + } else { + ms_error("Invalid tunnel mode '%s'", string); + return LinphoneTunnelModeDisable; + } + } else { + return LinphoneTunnelModeDisable; + } +} + +static const char *_tunnel_mode_to_string(LinphoneTunnelMode mode) { + return _tunnel_mode_str[mode]; +} + /** * Startup tunnel using configuration. * Called internally from linphonecore at startup. */ void linphone_tunnel_configure(LinphoneTunnel *tunnel){ - bool_t enabled=(bool_t)lp_config_get_int(config(tunnel),"tunnel","enabled",FALSE); + LinphoneTunnelMode mode = _string_to_tunnel_mode(lp_config_get_string(config(tunnel), "tunnel", "mode", NULL)); + bool_t tunnelizeSIPPackets = (bool_t)lp_config_get_int(config(tunnel), "tunnel", "sip", TRUE); linphone_tunnel_enable_logs_with_handler(tunnel,TRUE,my_ortp_logv); linphone_tunnel_load_config(tunnel); - linphone_tunnel_enable(tunnel, enabled); + linphone_tunnel_enable_sip(tunnel, tunnelizeSIPPackets); + linphone_tunnel_set_mode(tunnel, mode); } +/* Deprecated functions */ +void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled) { + if(enabled) linphone_tunnel_set_mode(tunnel, LinphoneTunnelModeEnable); + else linphone_tunnel_set_mode(tunnel, LinphoneTunnelModeDisable); +} + +bool_t linphone_tunnel_enabled(const LinphoneTunnel *tunnel) { + return linphone_tunnel_get_mode(tunnel) == LinphoneTunnelModeEnable; +} + +void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel) { + linphone_tunnel_set_mode(tunnel, LinphoneTunnelModeAuto); +} + +bool_t linphone_tunnel_auto_detect_enabled(LinphoneTunnel *tunnel) { + return linphone_tunnel_get_mode(tunnel) == LinphoneTunnelModeAuto; +} diff --git a/coreapi/linphone_tunnel.h b/coreapi/linphone_tunnel.h index 9b33e32f8..3a2c66330 100644 --- a/coreapi/linphone_tunnel.h +++ b/coreapi/linphone_tunnel.h @@ -50,10 +50,16 @@ extern "C" typedef struct _LinphoneTunnelConfig LinphoneTunnelConfig; +typedef enum _LinphoneTunnelMode { + LinphoneTunnelModeDisable, + LinphoneTunnelModeEnable, + LinphoneTunnelModeAuto +} LinphoneTunnelMode; + /** * Create a new tunnel configuration */ -LINPHONE_PUBLIC LinphoneTunnelConfig *linphone_tunnel_config_new(); +LINPHONE_PUBLIC LinphoneTunnelConfig *linphone_tunnel_config_new(void); /** * Set address of server. @@ -131,51 +137,49 @@ LINPHONE_PUBLIC void linphone_tunnel_config_destroy(LinphoneTunnelConfig *tunnel LINPHONE_PUBLIC void linphone_tunnel_add_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config); /** - * Remove tunnel server configuration - * + * @brief Remove tunnel server configuration * @param tunnel object * @param tunnel_config object */ LINPHONE_PUBLIC void linphone_tunnel_remove_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config); /** - * @param tunnel object - * returns a string of space separated list of host:port of tunnel server addresses - * */ -LINPHONE_PUBLIC const MSList *linphone_tunnel_get_servers(LinphoneTunnel *tunnel); + * @brief Get added servers + * @param tunnel A LinphoneTunnel object + * @return A list of LinphoneTunnelConfig objects + */ +LINPHONE_PUBLIC const MSList *linphone_tunnel_get_servers(const LinphoneTunnel *tunnel); /** - * @param tunnel object - * Removes all tunnel server address previously entered with addServer() + * @brief Removes all tunnel server address previously entered with addServer() + * @param tunnel A LinphoneTunnel object **/ LINPHONE_PUBLIC void linphone_tunnel_clean_servers(LinphoneTunnel *tunnel); /** - * Sets whether tunneling of SIP and RTP is required. + * @brief Set tunnel mode + * The tunnel mode can be 'enable', 'disable' or 'auto' + * If the mode is set to 'auto', the tunnel manager will try to established an RTP session + * with the tunnel server on the UdpMirrorPort. If the connection fail, the tunnel is automatically + * activated whereas the tunnel is automatically disabled if the connection succeed. * @param tunnel object - * @param enabled If true enter in tunneled mode, if false exits from tunneled mode. - * The TunnelManager takes care of refreshing SIP registration when switching on or off the tunneled mode. - * + * @param mode See #LinphoneTunnelMode **/ -LINPHONE_PUBLIC void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled); +LINPHONE_PUBLIC void linphone_tunnel_set_mode(LinphoneTunnel *tunnel, LinphoneTunnelMode mode); /** - * @param tunnel object - * Returns a boolean indicating whether tunneled operation is enabled. + * @brief Get the tunnel mode + * @param tunnel A LinphoneTunnel object + * @return Return a #LinphoneTunnelMode enumeration **/ -LINPHONE_PUBLIC bool_t linphone_tunnel_enabled(LinphoneTunnel *tunnel); +LINPHONE_PUBLIC LinphoneTunnelMode linphone_tunnel_get_mode(const LinphoneTunnel *tunnel); /** - * @param tunnel object - * Returns a boolean indicating whether tunnel is connected successfully. + * @brief Check whether the tunnel is connected + * @param tunnel LinphoneTunnel object + * @return True if the tunnel is connected **/ -bool_t linphone_tunnel_connected(LinphoneTunnel *tunnel); - -/** - * @param tunnel object - * Returns a boolean indicating whether tunnel is connected successfully. -**/ -bool_t linphone_tunnel_connected(LinphoneTunnel *tunnel); +LINPHONE_PUBLIC bool_t linphone_tunnel_connected(const LinphoneTunnel *tunnel); /** * @param tunnel object @@ -187,20 +191,18 @@ bool_t linphone_tunnel_connected(LinphoneTunnel *tunnel); LINPHONE_PUBLIC void linphone_tunnel_reconnect(LinphoneTunnel *tunnel); /** - * Start tunnel need detection. - * @param tunnel object - * In auto detect mode, the tunnel manager try to establish a real time rtp cummunication with the tunnel server on specified port. - *
In case of success, the tunnel is automatically turned off. Otherwise, if no udp commmunication is feasible, tunnel mode is turned on. - *
Call this method each time to run the auto detection algorithm + * @brief Set whether SIP packets must be directly sent to a UA or pass through the tunnel + * @param tunnel Tunnel to configure + * @param enable If true, SIP packets shall pass through the tunnel */ -LINPHONE_PUBLIC void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel); +LINPHONE_PUBLIC void linphone_tunnel_enable_sip(LinphoneTunnel *tunnel, bool_t enable); /** - * Tells whether tunnel auto detection is enabled. - * @param[in] tunnel LinphoneTunnel object. - * @return TRUE if auto detection is enabled, FALSE otherwise. + * @brief Check whether tunnel is set to transport SIP packets + * @param tunnel Tunnel to check + * @return True, SIP packets shall pass through through tunnel */ -LINPHONE_PUBLIC bool_t linphone_tunnel_auto_detect_enabled(LinphoneTunnel *tunnel); +LINPHONE_PUBLIC bool_t linphone_tunnel_sip_enabled(const LinphoneTunnel *tunnel); /** * Set an optional http proxy to go through when connecting to tunnel server. @@ -222,8 +224,50 @@ LINPHONE_PUBLIC void linphone_tunnel_set_http_proxy(LinphoneTunnel *tunnel, cons **/ LINPHONE_PUBLIC void linphone_tunnel_get_http_proxy(LinphoneTunnel*tunnel,const char **host, int *port, const char **username, const char **passwd); +/** + * @brief Set authentication info for the http proxy + * @param tunnel LinphoneTunnel object + * @param username User name + * @param passwd Password + */ LINPHONE_PUBLIC void linphone_tunnel_set_http_proxy_auth_info(LinphoneTunnel*tunnel, const char* username,const char* passwd); +/** + * @deprecated Replaced by linphone_tunnel_set_mode() + * @brief Sets whether tunneling of SIP and RTP is required. + * @param tunnel object + * @param enabled If true enter in tunneled mode, if false exits from tunneled mode. + * The TunnelManager takes care of refreshing SIP registration when switching on or off the tunneled mode. + * +**/ +LINPHONE_PUBLIC void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled); + +/** + * @deprecated Replaced by linphone_tunnel_get_mode() + * @brief Check whether tunnel is enabled + * @param tunnel Tunnel object + * @return Returns a boolean indicating whether tunneled operation is enabled. +**/ +LINPHONE_PUBLIC bool_t linphone_tunnel_enabled(const LinphoneTunnel *tunnel); + +/** + * @deprecated Replaced by linphone_tunnel_set_mode(LinphoneTunnelModeAuto) + * @brief Start tunnel need detection. + * @param tunnel object + * In auto detect mode, the tunnel manager try to establish a real time rtp cummunication with the tunnel server on specified port. + *
In case of success, the tunnel is automatically turned off. Otherwise, if no udp commmunication is feasible, tunnel mode is turned on. + *
Call this method each time to run the auto detection algorithm + */ +LINPHONE_PUBLIC void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel); + +/** + * @deprecated Replaced by linphone_tunnel_get_mode() + * @brief Tells whether tunnel auto detection is enabled. + * @param[in] tunnel LinphoneTunnel object. + * @return TRUE if auto detection is enabled, FALSE otherwise. + */ +LINPHONE_PUBLIC bool_t linphone_tunnel_auto_detect_enabled(LinphoneTunnel *tunnel); + /** * @} diff --git a/coreapi/linphone_tunnel_stubs.c b/coreapi/linphone_tunnel_stubs.c index c208dd249..72693463b 100644 --- a/coreapi/linphone_tunnel_stubs.c +++ b/coreapi/linphone_tunnel_stubs.c @@ -29,7 +29,7 @@ #include "lpconfig.h" -LinphoneTunnel* linphone_core_get_tunnel(LinphoneCore *lc){ +LinphoneTunnel* linphone_core_get_tunnel(const LinphoneCore *lc){ return lc->tunnel; } @@ -45,21 +45,21 @@ void linphone_tunnel_add_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tu void linphone_tunnel_remove_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config){ } -const MSList *linphone_tunnel_get_servers(LinphoneTunnel *tunnel){ +const MSList *linphone_tunnel_get_servers(const LinphoneTunnel *tunnel){ return NULL; } void linphone_tunnel_clean_servers(LinphoneTunnel *tunnel){ } -void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled){ +void linphone_tunnel_set_mode(LinphoneTunnel *tunnel, LinphoneTunnelMode mode) { } -bool_t linphone_tunnel_enabled(LinphoneTunnel *tunnel){ - return FALSE; +LinphoneTunnelMode linphone_tunnel_get_mode(const LinphoneTunnel *tunnel){ + return LinphoneTunnelModeDisable; } -bool_t linphone_tunnel_connected(LinphoneTunnel *tunnel){ +bool_t linphone_tunnel_connected(const LinphoneTunnel *tunnel){ return FALSE; } @@ -79,9 +79,14 @@ void linphone_tunnel_get_http_proxy(LinphoneTunnel*tunnel,const char **host, int void linphone_tunnel_reconnect(LinphoneTunnel *tunnel){ } -void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel){ -} - void linphone_tunnel_configure(LinphoneTunnel *tunnel){ } +void linphone_tunnel_enable_sip(LinphoneTunnel *tunnel, bool_t enable) {} +bool_t linphone_tunnel_sip_enabled(const LinphoneTunnel *tunnel) { return FALSE; } + +/* Deprecated functions */ +void linphone_tunnel_enable(LinphoneTunnel *tunnel, bool_t enabled) {} +bool_t linphone_tunnel_enabled(const LinphoneTunnel *tunnel) { return FALSE; } +void linphone_tunnel_auto_detect(LinphoneTunnel *tunnel) {} +bool_t linphone_tunnel_auto_detect_enabled(LinphoneTunnel *tunnel) { return FALSE; } diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 8f82311fd..2517c4a4c 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -37,6 +37,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "mediastreamer2/mseventqueue.h" #include "mediastreamer2/mssndcard.h" +static const char EC_STATE_STORE[] = ".linphone.ecstate"; + static void linphone_call_stats_uninit(LinphoneCallStats *stats); #ifdef VIDEO_ENABLED @@ -151,17 +153,14 @@ static uint16_t linphone_call_get_avpf_rr_interval(const LinphoneCall *call) { } static void propagate_encryption_changed(LinphoneCall *call){ - LinphoneCore *lc=call->core; if (!linphone_call_all_streams_encrypted(call)) { ms_message("Some streams are not encrypted"); - call->current_params.media_encryption=LinphoneMediaEncryptionNone; - if (lc->vtable.call_encryption_changed) - lc->vtable.call_encryption_changed(call->core, call, FALSE, call->auth_token); + call->current_params->media_encryption=LinphoneMediaEncryptionNone; + linphone_core_notify_call_encryption_changed(call->core, call, FALSE, call->auth_token); } else { ms_message("All streams are encrypted"); - call->current_params.media_encryption=LinphoneMediaEncryptionZRTP; - if (lc->vtable.call_encryption_changed) - lc->vtable.call_encryption_changed(call->core, call, TRUE, call->auth_token); + call->current_params->media_encryption=LinphoneMediaEncryptionZRTP; + linphone_core_notify_call_encryption_changed(call->core, call, TRUE, call->auth_token); } } @@ -171,9 +170,9 @@ static void linphone_call_audiostream_encryption_changed(void *data, bool_t encr call = (LinphoneCall *)data; - if (encrypted && call->core->vtable.display_status != NULL) { + if (encrypted) { snprintf(status,sizeof(status)-1,_("Authentication token is %s"),call->auth_token); - call->core->vtable.display_status(call->core, status); + linphone_core_notify_display_status(call->core, status); } propagate_encryption_changed(call); @@ -236,6 +235,14 @@ static MSList *make_codec_list(LinphoneCore *lc, const MSList *codecs, int bandw for(it=codecs;it!=NULL;it=it->next){ PayloadType *pt=(PayloadType*)it->data; if (pt->flags & PAYLOAD_TYPE_ENABLED){ + int sample_rate = payload_type_get_rate(pt); + + if( strcasecmp("G722",pt->mime_type) == 0 ){ + /* G722 spec says 8000 but the codec actually requires 16000 */ + ms_debug("Correcting sample rate for G722"); + sample_rate = 16000; + } + if (bandwidth_limit>0 && !linphone_core_is_payload_type_usable_for_bandwidth(lc,pt,bandwidth_limit)){ ms_message("Codec %s/%i eliminated because of audio bandwidth constraint of %i kbit/s", pt->mime_type,pt->clock_rate,bandwidth_limit); @@ -244,7 +251,7 @@ static MSList *make_codec_list(LinphoneCore *lc, const MSList *codecs, int bandw if (linphone_core_check_payload_type_usability(lc,pt)){ l=ms_list_append(l,payload_type_clone(pt)); nb++; - if (max_sample_rate && payload_type_get_rate(pt)>*max_sample_rate) *max_sample_rate=payload_type_get_rate(pt); + if (max_sample_rate && sample_rate>*max_sample_rate) *max_sample_rate=sample_rate; } } if ((nb_codecs_limit > 0) && (nb >= nb_codecs_limit)) break; @@ -305,7 +312,7 @@ static void setup_encryption_keys(LinphoneCall *call, SalMediaDescription *md){ for(i=0; inb_streams; i++) { if (!sal_stream_description_active(&md->streams[i])) continue; if (sal_stream_description_has_srtp(&md->streams[i]) == TRUE) { - if (keep_srtp_keys && old_md && sal_stream_description_has_srtp(&old_md->streams[i]) == TRUE){ + if (keep_srtp_keys && old_md && (sal_stream_description_active(&old_md->streams[i]) == TRUE) && (sal_stream_description_has_srtp(&old_md->streams[i]) == TRUE)) { int j; ms_message("Keeping same crypto keys."); for(j=0;jstreams[i])) continue; for (pt_it = md->streams[i].payloads; pt_it != NULL; pt_it = pt_it->next) { pt = (PayloadType *)pt_it->data; - if (call->params.avpf_enabled == TRUE) { + if (call->params->avpf_enabled == TRUE) { payload_type_set_flag(pt, PAYLOAD_TYPE_RTCP_FEEDBACK_ENABLED); avpf_params = payload_type_get_avpf_params(pt); - avpf_params.trr_interval = call->params.avpf_rr_interval; + avpf_params.trr_interval = call->params->avpf_rr_interval; } else { payload_type_unset_flag(pt, PAYLOAD_TYPE_RTCP_FEEDBACK_ENABLED); memset(&avpf_params, 0, sizeof(avpf_params)); @@ -348,20 +355,20 @@ static void setup_rtcp_xr(LinphoneCall *call, SalMediaDescription *md) { LinphoneCore *lc = call->core; int i; - md->rtcp_xr.enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_enabled", 0); + md->rtcp_xr.enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_enabled", 1); if (md->rtcp_xr.enabled == TRUE) { - const char *rcvr_rtt_mode = lp_config_get_string(lc->config, "rtp", "rtcp_xr_rcvr_rtt_mode", "none"); + const char *rcvr_rtt_mode = lp_config_get_string(lc->config, "rtp", "rtcp_xr_rcvr_rtt_mode", "all"); if (strcasecmp(rcvr_rtt_mode, "all") == 0) md->rtcp_xr.rcvr_rtt_mode = OrtpRtcpXrRcvrRttAll; else if (strcasecmp(rcvr_rtt_mode, "sender") == 0) md->rtcp_xr.rcvr_rtt_mode = OrtpRtcpXrRcvrRttSender; else md->rtcp_xr.rcvr_rtt_mode = OrtpRtcpXrRcvrRttNone; if (md->rtcp_xr.rcvr_rtt_mode != OrtpRtcpXrRcvrRttNone) { - md->rtcp_xr.rcvr_rtt_max_size = lp_config_get_int(lc->config, "rtp", "rtcp_xr_rcvr_rtt_max_size", 0); + md->rtcp_xr.rcvr_rtt_max_size = lp_config_get_int(lc->config, "rtp", "rtcp_xr_rcvr_rtt_max_size", 10000); } - md->rtcp_xr.stat_summary_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_stat_summary_enabled", 0); + md->rtcp_xr.stat_summary_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_stat_summary_enabled", 1); if (md->rtcp_xr.stat_summary_enabled == TRUE) { md->rtcp_xr.stat_summary_flags = OrtpRtcpXrStatSummaryLoss | OrtpRtcpXrStatSummaryDup | OrtpRtcpXrStatSummaryJitt | OrtpRtcpXrStatSummaryTTL; } - md->rtcp_xr.voip_metrics_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_voip_metrics_enabled", 0); + md->rtcp_xr.voip_metrics_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_xr_voip_metrics_enabled", 1); } for (i = 0; i < md->nb_streams; i++) { if (!sal_stream_description_active(&md->streams[i])) continue; @@ -374,13 +381,6 @@ void linphone_call_increment_local_media_description(LinphoneCall *call){ md->session_ver++; } -static SalMediaProto get_proto_from_call_params(const LinphoneCallParams *params) { - if ((params->media_encryption == LinphoneMediaEncryptionSRTP) && params->avpf_enabled) return SalProtoRtpSavpf; - if (params->media_encryption == LinphoneMediaEncryptionSRTP) return SalProtoRtpSavp; - if (params->avpf_enabled) return SalProtoRtpAvpf; - return SalProtoRtpAvp; -} - void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall *call){ MSList *l; PayloadType *pt; @@ -391,9 +391,9 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall * SalMediaDescription *md=sal_media_description_new(); LinphoneAddress *addr; char* local_ip=call->localip; - const char *subject=linphone_call_params_get_session_name(&call->params); + const char *subject=linphone_call_params_get_session_name(call->params); - linphone_core_adapt_to_network(lc,call->ping_time,&call->params); + linphone_core_adapt_to_network(lc,call->ping_time,call->params); if (call->dest_proxy) me=linphone_proxy_config_get_identity(call->dest_proxy); @@ -409,8 +409,8 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall * strncpy(md->username,linphone_address_get_username(addr),sizeof(md->username)); if (subject) strncpy(md->name,subject,sizeof(md->name)); - if (call->params.down_bw) - md->bandwidth=call->params.down_bw; + if (call->params->down_bw) + md->bandwidth=call->params->down_bw; else md->bandwidth=linphone_core_get_download_bandwidth(lc); /*set audio capabilities */ @@ -419,19 +419,19 @@ void linphone_call_make_local_media_description(LinphoneCore *lc, LinphoneCall * strncpy(md->streams[0].name,"Audio",sizeof(md->streams[0].name)-1); md->streams[0].rtp_port=call->media_ports[0].rtp_port; md->streams[0].rtcp_port=call->media_ports[0].rtcp_port; - md->streams[0].proto=get_proto_from_call_params(&call->params); + md->streams[0].proto=get_proto_from_call_params(call->params); md->streams[0].type=SalAudio; - if (call->params.down_ptime) - md->streams[0].ptime=call->params.down_ptime; + if (call->params->down_ptime) + md->streams[0].ptime=call->params->down_ptime; else md->streams[0].ptime=linphone_core_get_download_ptime(lc); - l=make_codec_list(lc,lc->codecs_conf.audio_codecs,call->params.audio_bw,&md->streams[0].max_rate,-1); + l=make_codec_list(lc,lc->codecs_conf.audio_codecs,call->params->audio_bw,&md->streams[0].max_rate,-1); pt=payload_type_clone(rtp_profile_get_payload_from_mime(lc->default_profile,"telephone-event")); l=ms_list_append(l,pt); md->streams[0].payloads=l; nb_active_streams++; - if (call->params.has_video){ + if (call->params->has_video){ strncpy(md->streams[1].rtp_addr,local_ip,sizeof(md->streams[1].rtp_addr)); strncpy(md->streams[1].rtcp_addr,local_ip,sizeof(md->streams[1].rtcp_addr)); strncpy(md->streams[1].name,"Video",sizeof(md->streams[1].name)-1); @@ -562,15 +562,13 @@ static void port_config_set(LinphoneCall *call, int stream_index, int min_port, static void linphone_call_init_common(LinphoneCall *call, LinphoneAddress *from, LinphoneAddress *to){ int min_port, max_port; ms_message("New LinphoneCall [%p] initialized (LinphoneCore version: %s)",call,linphone_core_get_version()); - call->magic=linphone_call_magic; - call->refcnt=1; call->state=LinphoneCallIdle; call->transfer_state = LinphoneCallIdle; call->media_start_time=0; - call->log=linphone_call_log_new(call, from, to); - call->owns_call_log=TRUE; + call->log=linphone_call_log_new(call->dir, from, to); call->camera_enabled=TRUE; - call->current_params.media_encryption=LinphoneMediaEncryptionNone; + call->current_params = linphone_call_params_new(); + call->current_params->media_encryption=LinphoneMediaEncryptionNone; linphone_core_get_audio_port_range(call->core, &min_port, &max_port); port_config_set(call,0,min_port,max_port); @@ -612,11 +610,11 @@ void linphone_call_create_op(LinphoneCall *call){ if (call->op) sal_op_release(call->op); call->op=sal_op_new(call->core->sal); sal_op_set_user_pointer(call->op,call); - if (call->params.referer) - sal_call_set_referer(call->op,call->params.referer->op); - linphone_configure_op(call->core,call->op,call->log->to,call->params.custom_headers,FALSE); - if (call->params.privacy != LinphonePrivacyDefault) - sal_op_set_privacy(call->op,(SalPrivacyMask)call->params.privacy); + if (call->params->referer) + sal_call_set_referer(call->op,call->params->referer->op); + linphone_configure_op(call->core,call->op,call->log->to,call->params->custom_headers,FALSE); + if (call->params->privacy != LinphonePrivacyDefault) + sal_op_set_privacy(call->op,(SalPrivacyMask)call->params->privacy); /*else privacy might be set by proxy */ } @@ -639,21 +637,70 @@ static void linphone_call_outgoing_select_ip_version(LinphoneCall *call, Linphon }else call->af=AF_INET; } +/** + * Fill the local ip that routes to the internet according to the destination, or guess it by other special means (upnp). + */ +static void linphone_call_get_local_ip(LinphoneCall *call, const LinphoneAddress *remote_addr){ + const char *ip; + int af = call->af; + const char *dest = NULL; + if (call->dest_proxy == NULL) { + struct addrinfo hints; + struct addrinfo *res = NULL; + int err; + const char *domain = linphone_address_get_domain(remote_addr); + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_flags = AI_NUMERICHOST; + err = getaddrinfo(domain, NULL, &hints, &res); + if (err == 0) { + dest = domain; + } + if (res != NULL) freeaddrinfo(res); + } + if (_linphone_core_get_firewall_policy(call->core)==LinphonePolicyUseNatAddress + && (ip=linphone_core_get_nat_address_resolved(call->core))!=NULL){ + strncpy(call->localip,ip,LINPHONE_IPADDR_SIZE); + return; + } +#ifdef BUILD_UPNP + else if (call->core->upnp != NULL && linphone_core_get_firewall_policy(call->core)==LinphonePolicyUseUpnp && + linphone_upnp_context_get_state(call->core->upnp) == LinphoneUpnpStateOk) { + ip = linphone_upnp_context_get_external_ipaddress(call->core->upnp); + strncpy(call->localip,ip,LINPHONE_IPADDR_SIZE); + return; + } +#endif //BUILD_UPNP + linphone_core_get_local_ip(call->core, af, dest, call->localip); +} + +static void linphone_call_destroy(LinphoneCall *obj); + +BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneCall); + +BELLE_SIP_INSTANCIATE_VPTR(LinphoneCall, belle_sip_object_t, + (belle_sip_object_destroy_t)linphone_call_destroy, + NULL, // clone + NULL, // marshal + FALSE +); + LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, const LinphoneCallParams *params, LinphoneProxyConfig *cfg){ - LinphoneCall *call=ms_new0(LinphoneCall,1); + LinphoneCall *call = belle_sip_object_new(LinphoneCall); call->dir=LinphoneCallOutgoing; call->core=lc; linphone_call_outgoing_select_ip_version(call,to,cfg); - linphone_core_get_local_ip(lc,call->af,call->localip); + linphone_call_get_local_ip(call, to); linphone_call_init_common(call,from,to); - _linphone_call_params_copy(&call->params,params); + call->params = linphone_call_params_copy(params); - if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) { + if (_linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) { call->ice_session = ice_session_new(); ice_session_set_role(call->ice_session, IR_Controlling); } - if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseStun) { + if (_linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseStun) { call->ping_time=linphone_core_run_stun_tests(call->core,call); } #ifdef BUILD_UPNP @@ -683,25 +730,24 @@ static void linphone_call_incoming_select_ip_version(LinphoneCall *call){ * Fix call parameters on incoming call to eg. enable AVPF if the incoming call propose it and it is not enabled locally. */ void linphone_call_set_compatible_incoming_call_parameters(LinphoneCall *call, const SalMediaDescription *md) { - call->params.has_video &= linphone_core_media_description_contains_video_stream(md); + call->params->has_video &= linphone_core_media_description_contains_video_stream(md); /* Handle AVPF and SRTP. */ - call->params.avpf_enabled = sal_media_description_has_avpf(md); - if (call->params.avpf_enabled == TRUE) { + call->params->avpf_enabled = sal_media_description_has_avpf(md); + if (call->params->avpf_enabled == TRUE) { if (call->dest_proxy != NULL) { - call->params.avpf_rr_interval = linphone_proxy_config_get_avpf_rr_interval(call->dest_proxy) * 1000; + call->params->avpf_rr_interval = linphone_proxy_config_get_avpf_rr_interval(call->dest_proxy) * 1000; } else { - call->params.avpf_rr_interval = 5000; + call->params->avpf_rr_interval = linphone_core_get_avpf_rr_interval(call->core)*1000; } } if ((sal_media_description_has_srtp(md) == TRUE) && (media_stream_srtp_supported() == TRUE)) { - call->params.media_encryption = LinphoneMediaEncryptionSRTP; + call->params->media_encryption = LinphoneMediaEncryptionSRTP; } } LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, SalOp *op){ - LinphoneCall *call=ms_new0(LinphoneCall,1); - char *from_str; + LinphoneCall *call = belle_sip_object_new(LinphoneCall); const SalMediaDescription *md; LinphoneFirewallPolicy fpol; @@ -721,36 +767,39 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro /*the following sends an option request back to the caller so that we get a chance to discover our nat'd address before answering.*/ call->ping_op=sal_op_new(lc->sal); - from_str=linphone_address_as_string_uri_only(from); + + linphone_configure_op(lc, call->ping_op, from, NULL, FALSE); + sal_op_set_route(call->ping_op,sal_op_get_network_origin(op)); sal_op_set_user_pointer(call->ping_op,call); - sal_ping(call->ping_op,linphone_core_find_best_identity(lc,from),from_str); - ms_free(from_str); + + sal_ping(call->ping_op,sal_op_get_from(call->ping_op), sal_op_get_to(call->ping_op)); } } linphone_address_clean(from); - linphone_core_get_local_ip(lc,call->af,call->localip); + linphone_call_get_local_ip(call, from); linphone_call_init_common(call, from, to); + call->params = linphone_call_params_new(); call->log->call_id=ms_strdup(sal_op_get_call_id(op)); /*must be known at that time*/ call->dest_proxy = linphone_core_lookup_known_proxy(call->core, to); - linphone_core_init_default_params(lc, &call->params); + linphone_core_init_default_params(lc, call->params); /* * Initialize call parameters according to incoming call parameters. This is to avoid to ask later (during reINVITEs) for features that the remote * end apparently does not support. This features are: privacy, video */ /*set privacy*/ - call->current_params.privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op); + call->current_params->privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op); /*set video support */ md=sal_call_get_remote_media_description(op); - call->params.has_video = lc->video_policy.automatically_accept; + call->params->has_video = lc->video_policy.automatically_accept; if (md) { // It is licit to receive an INVITE without SDP // In this case WE chose the media parameters according to policy. linphone_call_set_compatible_incoming_call_parameters(call, md); } - fpol=linphone_core_get_firewall_policy(call->core); + fpol=_linphone_core_get_firewall_policy(call->core); /*create the ice session now if ICE is required*/ if (fpol==LinphonePolicyUseIce){ if (md){ @@ -809,7 +858,6 @@ static void linphone_call_set_terminated(LinphoneCall *call){ linphone_core_update_allocated_audio_bandwidth(lc); linphone_call_stats_uninit(&call->stats[0]); linphone_call_stats_uninit(&call->stats[1]); - call->owns_call_log=FALSE; linphone_call_log_completed(call); @@ -830,10 +878,10 @@ static void linphone_call_set_terminated(LinphoneCall *call){ } void linphone_call_fix_call_parameters(LinphoneCall *call){ - call->params.has_video=call->current_params.has_video; + call->params->has_video=call->current_params->has_video; - if (call->params.media_encryption != LinphoneMediaEncryptionZRTP) /*in case of ZRTP call parameter are handle after zrtp negociation*/ - call->params.media_encryption=call->current_params.media_encryption; + if (call->params->media_encryption != LinphoneMediaEncryptionZRTP) /*in case of ZRTP call parameter are handle after zrtp negociation*/ + call->params->media_encryption=call->current_params->media_encryption; } const char *linphone_call_state_to_string(LinphoneCallState cs){ @@ -880,7 +928,11 @@ const char *linphone_call_state_to_string(LinphoneCallState cs){ return "undefined state"; } -void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const char *message){ +void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const char *message) { + linphone_call_set_state_base(call, cstate, message,FALSE); +} + +void linphone_call_set_state_base(LinphoneCall *call, LinphoneCallState cstate, const char *message,bool_t silently){ LinphoneCore *lc=call->core; if (call->state!=cstate){ @@ -919,8 +971,8 @@ void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const call->media_start_time=time(NULL); } - if (lc->vtable.call_state_changed) - lc->vtable.call_state_changed(lc,call,cstate,message); + if (!silently) + linphone_core_notify_call_state_changed(lc,call,cstate,message); linphone_reporting_call_state_updated(call); @@ -982,15 +1034,17 @@ static void linphone_call_destroy(LinphoneCall *obj) if (obj->transfer_target){ linphone_call_unref(obj->transfer_target); } - if (obj->owns_call_log) - linphone_call_log_destroy(obj->log); + if (obj->log) + linphone_call_log_unref(obj->log); if (obj->auth_token) { ms_free(obj->auth_token); } - linphone_call_params_uninit(&obj->params); - linphone_call_params_uninit(&obj->current_params); + linphone_call_params_unref(obj->params); + linphone_call_params_unref(obj->current_params); + if (obj->remote_params != NULL) { + linphone_call_params_unref(obj->remote_params); + } sal_error_info_reset(&obj->non_op_error); - ms_free(obj); } /** @@ -998,27 +1052,13 @@ static void linphone_call_destroy(LinphoneCall *obj) * @{ **/ -/** - * Increments the call 's reference count. - * An application that wishes to retain a pointer to call object - * must use this function to unsure the pointer remains - * valid. Once the application no more needs this pointer, - * it must call linphone_call_unref(). -**/ LinphoneCall * linphone_call_ref(LinphoneCall *obj){ - obj->refcnt++; + belle_sip_object_ref(obj); return obj; } -/** - * Decrements the call object reference count. - * See linphone_call_ref(). -**/ void linphone_call_unref(LinphoneCall *obj){ - obj->refcnt--; - if (obj->refcnt==0){ - linphone_call_destroy(obj); - } + belle_sip_object_unref(obj); } /** @@ -1028,35 +1068,35 @@ const LinphoneCallParams * linphone_call_get_current_params(LinphoneCall *call){ #ifdef VIDEO_ENABLED VideoStream *vstream; #endif - MS_VIDEO_SIZE_ASSIGN(call->current_params.sent_vsize, UNKNOWN); - MS_VIDEO_SIZE_ASSIGN(call->current_params.recv_vsize, UNKNOWN); + MS_VIDEO_SIZE_ASSIGN(call->current_params->sent_vsize, UNKNOWN); + MS_VIDEO_SIZE_ASSIGN(call->current_params->recv_vsize, UNKNOWN); #ifdef VIDEO_ENABLED vstream = call->videostream; if (vstream != NULL) { - call->current_params.sent_vsize = video_stream_get_sent_video_size(vstream); - call->current_params.recv_vsize = video_stream_get_received_video_size(vstream); - call->current_params.sent_fps = video_stream_get_sent_framerate(vstream); - call->current_params.received_fps = video_stream_get_received_framerate(vstream); + call->current_params->sent_vsize = video_stream_get_sent_video_size(vstream); + call->current_params->recv_vsize = video_stream_get_received_video_size(vstream); + call->current_params->sent_fps = video_stream_get_sent_framerate(vstream); + call->current_params->received_fps = video_stream_get_received_framerate(vstream); } #endif if (linphone_call_all_streams_encrypted(call)) { if (linphone_call_get_authentication_token(call)) { - call->current_params.media_encryption=LinphoneMediaEncryptionZRTP; + call->current_params->media_encryption=LinphoneMediaEncryptionZRTP; } else { - call->current_params.media_encryption=LinphoneMediaEncryptionSRTP; + call->current_params->media_encryption=LinphoneMediaEncryptionSRTP; } } else { - call->current_params.media_encryption=LinphoneMediaEncryptionNone; + call->current_params->media_encryption=LinphoneMediaEncryptionNone; } - call->current_params.avpf_enabled = linphone_call_all_streams_avpf_enabled(call); - if (call->current_params.avpf_enabled == TRUE) { - call->current_params.avpf_rr_interval = linphone_call_get_avpf_rr_interval(call); + call->current_params->avpf_enabled = linphone_call_all_streams_avpf_enabled(call); + if (call->current_params->avpf_enabled == TRUE) { + call->current_params->avpf_rr_interval = linphone_call_get_avpf_rr_interval(call); } else { - call->current_params.avpf_rr_interval = 0; + call->current_params->avpf_rr_interval = 0; } - return &call->current_params; + return call->current_params; } /** @@ -1066,10 +1106,12 @@ const LinphoneCallParams * linphone_call_get_current_params(LinphoneCall *call){ * supports video, encryption or whatever. **/ const LinphoneCallParams * linphone_call_get_remote_params(LinphoneCall *call){ - LinphoneCallParams *cp=&call->remote_params; - memset(cp,0,sizeof(*cp)); if (call->op){ - SalMediaDescription *md=sal_call_get_remote_media_description(call->op); + LinphoneCallParams *cp; + SalMediaDescription *md; + if (call->remote_params != NULL) linphone_call_params_unref(call->remote_params); + cp = call->remote_params = linphone_call_params_new(); + md=sal_call_get_remote_media_description(call->op); if (md) { SalStreamDescription *sd; unsigned int i; @@ -1092,7 +1134,7 @@ const LinphoneCallParams * linphone_call_get_remote_params(LinphoneCall *call){ } if (md->name[0]!='\0') linphone_call_params_set_session_name(cp,md->name); } - cp->custom_headers=(SalCustomHeader*)sal_op_get_recv_custom_header(call->op); + cp->custom_headers=sal_custom_header_clone((SalCustomHeader*)sal_op_get_recv_custom_header(call->op)); return cp; } return NULL; @@ -1139,27 +1181,26 @@ const LinphoneErrorInfo *linphone_call_get_error_info(const LinphoneCall *call){ } /** - * Get the user_pointer in the LinphoneCall + * Get the user pointer associated with the LinphoneCall * * @ingroup call_control - * - * return user_pointer an opaque user pointer that can be retrieved at any time + * @return an opaque user pointer that can be retrieved at any time **/ -void *linphone_call_get_user_pointer(LinphoneCall *call) +void *linphone_call_get_user_data(const LinphoneCall *call) { - return call->user_pointer; + return call->user_data; } /** - * Set the user_pointer in the LinphoneCall + * Set the user pointer associated with the LinphoneCall * * @ingroup call_control * - * the user_pointer is an opaque user pointer that can be retrieved at any time in the LinphoneCall + * the user pointer is an opaque user pointer that can be retrieved at any time in the LinphoneCall **/ -void linphone_call_set_user_pointer(LinphoneCall *call, void *user_pointer) +void linphone_call_set_user_data(LinphoneCall *call, void *user_pointer) { - call->user_pointer = user_pointer; + call->user_data = user_pointer; } /** @@ -1303,7 +1344,6 @@ int linphone_call_take_video_snapshot(LinphoneCall *call, const char *file){ return ms_filter_call_method(call->videostream->jpegwriter,MS_JPEG_WRITER_TAKE_SNAPSHOT,(void*)file); } ms_warning("Cannot take snapshot: no currently running video stream on this call."); - return -1; #endif return -1; } @@ -1313,7 +1353,7 @@ int linphone_call_take_video_snapshot(LinphoneCall *call, const char *file){ * Note that the snapshot is asynchronous, an application shall not assume that the file is created when the function returns. * @param call a LinphoneCall * @param file a path where to write the jpeg content. - * @return 0 if successfull, -1 otherwise (typically if jpeg format is not supported). + * @return 0 if successfull, -1 otherwise (typically if jpeg format is not supported). **/ int linphone_call_take_preview_snapshot(LinphoneCall *call, const char *file){ #ifdef VIDEO_ENABLED @@ -1333,194 +1373,6 @@ bool_t linphone_call_camera_enabled (const LinphoneCall *call){ return call->camera_enabled; } -/** - * Enable video stream. -**/ -void linphone_call_params_enable_video(LinphoneCallParams *cp, bool_t enabled){ - cp->has_video=enabled; -} - -/** - * Returns the audio codec used in the call, described as a PayloadType structure. -**/ -const PayloadType* linphone_call_params_get_used_audio_codec(const LinphoneCallParams *cp) { - return cp->audio_codec; -} - - -/** - * Returns the video codec used in the call, described as a PayloadType structure. -**/ -const PayloadType* linphone_call_params_get_used_video_codec(const LinphoneCallParams *cp) { - return cp->video_codec; -} - -MSVideoSize linphone_call_params_get_sent_video_size(const LinphoneCallParams *cp) { - return cp->sent_vsize; -} - -MSVideoSize linphone_call_params_get_received_video_size(const LinphoneCallParams *cp) { - return cp->recv_vsize; -} - -/** - * Gets the framerate of the video that is sent. - * @param[in] cp The call parameters. - * @return the actual sent framerate in frames per seconds, 0 if not available. - */ -float linphone_call_params_get_sent_framerate(const LinphoneCallParams *cp){ - return cp->sent_fps; -} - -/** - * Gets the framerate of the video that is received. - * @param[in] cp The call paramaters for which to get the received framerate. - * @return the actual received framerate in frames per seconds, 0 if not available. - */ -float linphone_call_params_get_received_framerate(const LinphoneCallParams *cp){ - return cp->received_fps; -} - -const char * linphone_call_params_get_rtp_profile(const LinphoneCallParams *cp) { - return sal_media_proto_to_string(get_proto_from_call_params(cp)); -} - -/** - * @ingroup call_control - * Use to know if this call has been configured in low bandwidth mode. - * This mode can be automatically discovered thanks to a stun server when activate_edge_workarounds=1 in section [net] of configuration file. - * An application that would have reliable way to know network capacity may not use activate_edge_workarounds=1 but instead manually configure - * low bandwidth mode with linphone_call_params_enable_low_bandwidth(). - *
When enabled, this param may transform a call request with video in audio only mode. - * @return TRUE if low bandwidth has been configured/detected - */ -bool_t linphone_call_params_low_bandwidth_enabled(const LinphoneCallParams *cp) { - return cp->low_bandwidth; -} - -/** - * @ingroup call_control - * Indicate low bandwith mode. - * Configuring a call to low bandwidth mode will result in the core to activate several settings for the call in order to ensure that bitrate usage - * is lowered to the minimum possible. Typically, ptime (packetization time) will be increased, audio codec's output bitrate will be targetted to 20kbit/s provided - * that it is achievable by the codec selected after SDP handshake. Video is automatically disabled. - * -**/ -void linphone_call_params_enable_low_bandwidth(LinphoneCallParams *cp, bool_t enabled){ - cp->low_bandwidth=enabled; -} - -/** - * Returns whether video is enabled. -**/ -bool_t linphone_call_params_video_enabled(const LinphoneCallParams *cp){ - return cp->has_video; -} - -/** - * Returns kind of media encryption selected for the call. -**/ -LinphoneMediaEncryption linphone_call_params_get_media_encryption(const LinphoneCallParams *cp) { - return cp->media_encryption; -} - -/** - * Set requested media encryption for a call. -**/ -void linphone_call_params_set_media_encryption(LinphoneCallParams *cp, LinphoneMediaEncryption e) { - cp->media_encryption = e; -} - - -/** - * Enable sending of real early media (during outgoing calls). -**/ -void linphone_call_params_enable_early_media_sending(LinphoneCallParams *cp, bool_t enabled){ - cp->real_early_media=enabled; -} - -/** - * Indicates whether sending of early media was enabled. -**/ -bool_t linphone_call_params_early_media_sending_enabled(const LinphoneCallParams *cp){ - return cp->real_early_media; -} - -/** - * Returns true if the call is part of the locally managed conference. -**/ -bool_t linphone_call_params_get_local_conference_mode(const LinphoneCallParams *cp){ - return cp->in_conference; -} - -/** - * Refine bandwidth settings for this call by setting a bandwidth limit for audio streams. - * As a consequence, codecs whose bitrates are not compatible with this limit won't be used. -**/ -void linphone_call_params_set_audio_bandwidth_limit(LinphoneCallParams *cp, int bandwidth){ - cp->audio_bw=bandwidth; -} - -void linphone_call_params_add_custom_header(LinphoneCallParams *params, const char *header_name, const char *header_value){ - params->custom_headers=sal_custom_header_append(params->custom_headers,header_name,header_value); -} - -const char *linphone_call_params_get_custom_header(const LinphoneCallParams *params, const char *header_name){ - return sal_custom_header_find(params->custom_headers,header_name); -} - -/** - * Returns the session name of the media session (ie in SDP). Subject from the SIP message can be retrieved using linphone_call_params_get_custom_header() and is different. - * @param cp the call parameters. -**/ -const char *linphone_call_params_get_session_name(const LinphoneCallParams *cp){ - return cp->session_name; -} - -/** - * Set the session name of the media session (ie in SDP). Subject from the SIP message (which is different) can be set using linphone_call_params_set_custom_header(). - * @param cp the call parameters. - * @param name the session name -**/ -void linphone_call_params_set_session_name(LinphoneCallParams *cp, const char *name){ - if (cp->session_name){ - ms_free(cp->session_name); - cp->session_name=NULL; - } - if (name) cp->session_name=ms_strdup(name); -} - -void _linphone_call_params_copy(LinphoneCallParams *ncp, const LinphoneCallParams *cp){ - if (ncp==cp) return; - memcpy(ncp,cp,sizeof(LinphoneCallParams)); - if (cp->record_file) ncp->record_file=ms_strdup(cp->record_file); - if (cp->session_name) ncp->session_name=ms_strdup(cp->session_name); - /* - * The management of the custom headers is not optimal. We copy everything while ref counting would be more efficient. - */ - if (cp->custom_headers) ncp->custom_headers=sal_custom_header_clone(cp->custom_headers); -} - -/** - * @ingroup call_control - * Set requested level of privacy for the call. - * \xmlonly javascript \endxmlonly - * @param params the call parameters to be modified - * @param privacy LinphonePrivacy to configure privacy - * */ -void linphone_call_params_set_privacy(LinphoneCallParams *params, LinphonePrivacyMask privacy) { - params->privacy=privacy; -} - -/** - * @ingroup call_control - * Get requested level of privacy for the call. - * @param params the call parameters - * @return Privacy mode - * */ -LinphonePrivacyMask linphone_call_params_get_privacy(const LinphoneCallParams *params) { - return params->privacy; -} /** * @ingroup call_control @@ -1538,27 +1390,6 @@ const char* linphone_privacy_to_string(LinphonePrivacy privacy) { default: return "Unknown privacy mode"; } } -/** - * Copy existing LinphoneCallParams to a new LinphoneCallParams object. -**/ -LinphoneCallParams * linphone_call_params_copy(const LinphoneCallParams *cp){ - LinphoneCallParams *ncp=ms_new0(LinphoneCallParams,1); - _linphone_call_params_copy(ncp,cp); - return ncp; -} - -void linphone_call_params_uninit(LinphoneCallParams *p){ - if (p->record_file) ms_free(p->record_file); - if (p->custom_headers) sal_custom_header_free(p->custom_headers); -} - -/** - * Destroy LinphoneCallParams. -**/ -void linphone_call_params_destroy(LinphoneCallParams *p){ - linphone_call_params_uninit(p); - ms_free(p); -} /** @@ -1578,16 +1409,22 @@ static void video_stream_event_cb(void *user_pointer, const MSFilter *f, const u LinphoneCall* call = (LinphoneCall*) user_pointer; switch (event_id) { case MS_VIDEO_DECODER_DECODING_ERRORS: - ms_warning("Case is MS_VIDEO_DECODER_DECODING_ERRORS"); + ms_warning("MS_VIDEO_DECODER_DECODING_ERRORS"); if (call->videostream && (video_stream_is_decoding_error_to_be_reported(call->videostream, 5000) == TRUE)) { video_stream_decoding_error_reported(call->videostream); linphone_call_send_vfu_request(call); } break; + case MS_VIDEO_DECODER_RECOVERED_FROM_ERRORS: + ms_message("MS_VIDEO_DECODER_RECOVERED_FROM_ERRORS"); + if (call->videostream) { + video_stream_decoding_error_recovered(call->videostream); + } + break; case MS_VIDEO_DECODER_FIRST_IMAGE_DECODED: ms_message("First video frame decoded successfully"); if (call->nextVideoFrameDecoded._func != NULL) - call->nextVideoFrameDecoded._func(call, call->nextVideoFrameDecoded._user_data); + call->nextVideoFrameDecoded._func(call, call->nextVideoFrameDecoded._user_data); break; case MS_VIDEO_DECODER_SEND_PLI: case MS_VIDEO_DECODER_SEND_SLI: @@ -1617,7 +1454,7 @@ static void port_config_set_random_choosed(LinphoneCall *call, int stream_index, static void _linphone_call_prepare_ice_for_stream(LinphoneCall *call, int stream_index, bool_t create_checklist){ MediaStream *ms=stream_index == 0 ? (MediaStream*)call->audiostream : (MediaStream*)call->videostream; - if ((linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) && (call->ice_session != NULL)){ + if ((_linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) && (call->ice_session != NULL)){ IceCheckList *cl; rtp_session_set_pktinfo(ms->sessions.rtp_session, TRUE); rtp_session_set_symmetric_rtp(ms->sessions.rtp_session, FALSE); @@ -1638,11 +1475,11 @@ int linphone_call_prepare_ice(LinphoneCall *call, bool_t incoming_offer){ SalMediaDescription *remote = NULL; bool_t has_video=FALSE; - if ((linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) && (call->ice_session != NULL)){ + if ((_linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) && (call->ice_session != NULL)){ if (incoming_offer){ remote=sal_call_get_remote_media_description(call->op); - has_video=call->params.has_video && linphone_core_media_description_contains_video_stream(remote); - }else has_video=call->params.has_video; + has_video=call->params->has_video && linphone_core_media_description_contains_video_stream(remote); + }else has_video=call->params->has_video; _linphone_call_prepare_ice_for_stream(call,0,TRUE); if (has_video) _linphone_call_prepare_ice_for_stream(call,1,TRUE); @@ -1672,6 +1509,7 @@ int linphone_call_prepare_ice(LinphoneCall *call, bool_t incoming_offer){ void linphone_call_init_audio_stream(LinphoneCall *call){ LinphoneCore *lc=call->core; AudioStream *audiostream; + const char *location; int dscp; if (call->audiostream != NULL) return; @@ -1695,16 +1533,24 @@ void linphone_call_init_audio_stream(LinphoneCall *call){ else if (strcasecmp(type,"full")==0) audio_stream_enable_echo_limiter(audiostream,ELControlFull); } + + /* equalizer location in the graph: 'mic' = in input graph, otherwise in output graph. + Any other value than mic will default to output graph for compatibility */ + location = lp_config_get_string(lc->config,"sound","eq_location","hp"); + audiostream->eq_loc = (strcasecmp(location,"mic") == 0) ? MSEqualizerMic : MSEqualizerHP; + ms_message("Equalizer location: %s", location); + audio_stream_enable_gain_control(audiostream,TRUE); if (linphone_core_echo_cancellation_enabled(lc)){ int len,delay,framesize; - const char *statestr=lp_config_get_string(lc->config,"sound","ec_state",NULL); + char *statestr=lp_config_read_relative_file(lc->config, EC_STATE_STORE); len=lp_config_get_int(lc->config,"sound","ec_tail_len",0); delay=lp_config_get_int(lc->config,"sound","ec_delay",0); framesize=lp_config_get_int(lc->config,"sound","ec_framesize",0); audio_stream_set_echo_canceller_params(audiostream,len,delay,framesize); if (statestr && audiostream->ec){ ms_filter_call_method(audiostream->ec,MS_ECHO_CANCELLER_SET_STATE_STRING,(void*)statestr); + ms_free(statestr); } } audio_stream_enable_automatic_gain_control(audiostream,linphone_core_agc_enabled(lc)); @@ -1718,7 +1564,11 @@ void linphone_call_init_audio_stream(LinphoneCall *call){ if (lc->rtptf){ RtpTransport *artp=lc->rtptf->audio_rtp_func(lc->rtptf->audio_rtp_func_data, call->media_ports[0].rtp_port); RtpTransport *artcp=lc->rtptf->audio_rtcp_func(lc->rtptf->audio_rtcp_func_data, call->media_ports[0].rtcp_port); - rtp_session_set_transports(audiostream->ms.sessions.rtp_session,artp,artcp); + RtpTransport *meta_rtp; + RtpTransport *meta_rtcp; + meta_rtp_transport_new(&meta_rtp,TRUE,artp, 0); + meta_rtp_transport_new(&meta_rtcp,FALSE,artcp, 0); + rtp_session_set_transports(audiostream->ms.sessions.rtp_session,meta_rtp,meta_rtcp); } call->audiostream_app_evq = ortp_ev_queue_new(); @@ -1756,9 +1606,13 @@ void linphone_call_init_video_stream(LinphoneCall *call){ if (lc->rtptf){ RtpTransport *vrtp=lc->rtptf->video_rtp_func(lc->rtptf->video_rtp_func_data, call->media_ports[1].rtp_port); RtpTransport *vrtcp=lc->rtptf->video_rtcp_func(lc->rtptf->video_rtcp_func_data, call->media_ports[1].rtcp_port); - rtp_session_set_transports(call->videostream->ms.sessions.rtp_session,vrtp,vrtcp); + RtpTransport *meta_rtp; + RtpTransport *meta_rtcp; + meta_rtp_transport_new(&meta_rtp,TRUE,vrtp, 0); + meta_rtp_transport_new(&meta_rtcp,FALSE,vrtcp, 0); + rtp_session_set_transports(call->videostream->ms.sessions.rtp_session,meta_rtp,meta_rtcp); } - call->videostream_app_evq = ortp_ev_queue_new(); + call->videostream_app_evq = ortp_ev_queue_new(); rtp_session_register_event_queue(call->videostream->ms.sessions.rtp_session,call->videostream_app_evq); _linphone_call_prepare_ice_for_stream(call,1,FALSE); #ifdef TEST_EXT_RENDERER @@ -1783,8 +1637,7 @@ static void linphone_core_dtmf_received(LinphoneCore *lc, int dtmf){ ms_warning("Bad dtmf value %i",dtmf); return; } - if (lc->vtable.dtmf_received != NULL) - lc->vtable.dtmf_received(lc, linphone_core_get_current_call(lc), dtmf_tab[dtmf]); + linphone_core_notify_dtmf_received(lc, linphone_core_get_current_call(lc), dtmf_tab[dtmf]); } static void parametrize_equalizer(LinphoneCore *lc, AudioStream *st){ @@ -1871,7 +1724,7 @@ static void post_configure_audio_streams(LinphoneCall*call){ AudioStream *st=call->audiostream; LinphoneCore *lc=call->core; _post_configure_audio_stream(st,lc,call->audio_muted); - if (lc->vtable.dtmf_received!=NULL){ + if (linphone_core_dtmf_received_has_listener(lc)){ audio_stream_play_received_dtmfs(call->audiostream,FALSE); } if (call->record_active) @@ -1882,7 +1735,7 @@ static int get_ideal_audio_bw(LinphoneCall *call, const SalMediaDescription *md, int remote_bw=0; int upload_bw; int total_upload_bw=linphone_core_get_upload_bandwidth(call->core); - const LinphoneCallParams *params=&call->params; + const LinphoneCallParams *params=call->params; bool_t will_use_video=linphone_core_media_description_contains_video_stream(md); bool_t forced=FALSE; @@ -1929,7 +1782,7 @@ static RtpProfile *make_profile(LinphoneCall *call, const SalMediaDescription *m bool_t first=TRUE; LinphoneCore *lc=call->core; int up_ptime=0; - const LinphoneCallParams *params=&call->params; + const LinphoneCallParams *params=call->params; *used_pt=-1; @@ -2037,6 +1890,7 @@ static void configure_rtp_session_for_rtcp_xr(LinphoneCore *lc, LinphoneCall *ca static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cname, bool_t muted, bool_t send_ringbacktone, bool_t use_arc){ LinphoneCore *lc=call->core; + LpConfig* conf; int used_pt=-1; char rtcp_tool[128]={0}; const SalStreamDescription *stream; @@ -2061,7 +1915,7 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna call->audio_profile=make_profile(call,call->resultdesc,stream,&used_pt); if (used_pt!=-1){ - call->current_params.audio_codec = rtp_profile_get_payload(call->audio_profile, used_pt); + call->current_params->audio_codec = rtp_profile_get_payload(call->audio_profile, used_pt); if (playcard==NULL) { ms_warning("No card defined for playback !"); } @@ -2081,15 +1935,20 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna /*playfile=NULL;*/ } if (send_ringbacktone){ + conf = linphone_core_get_config(lc); captcard=NULL; playfile=NULL;/* it is setup later*/ + if( conf && lp_config_get_int(conf,"sound","send_ringback_without_playback", 0) == 1){ + playcard = NULL; + recfile = NULL; + } } /*if playfile are supplied don't use soundcards*/ if (lc->use_files) { captcard=NULL; playcard=NULL; } - if (call->params.in_conference){ + if (call->params->in_conference){ /* first create the graph without soundcard resources*/ captcard=playcard=NULL; } @@ -2101,10 +1960,12 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna if (playcard && stream->max_rate>0) ms_snd_card_set_preferred_sample_rate(playcard, stream->max_rate); if (captcard && stream->max_rate>0) ms_snd_card_set_preferred_sample_rate(captcard, stream->max_rate); audio_stream_enable_adaptive_bitrate_control(call->audiostream,use_arc); + media_stream_set_adaptive_bitrate_algorithm(&call->audiostream->ms, + ms_qos_analyzer_algorithm_from_string(linphone_core_get_adaptive_rate_algorithm(lc))); audio_stream_enable_adaptive_jittcomp(call->audiostream, linphone_core_audio_adaptive_jittcomp_enabled(lc)); - if (!call->params.in_conference && call->params.record_file){ - audio_stream_mixed_record_open(call->audiostream,call->params.record_file); - call->current_params.record_file=ms_strdup(call->params.record_file); + if (!call->params->in_conference && call->params->record_file){ + audio_stream_mixed_record_open(call->audiostream,call->params->record_file); + call->current_params->record_file=ms_strdup(call->params->record_file); } /* valid local tags are > 0 */ if (sal_stream_description_has_srtp(stream) == TRUE) { @@ -2147,13 +2008,13 @@ static void linphone_call_start_audio_stream(LinphoneCall *call, const char *cna setup_ring_player(lc,call); } - if (call->params.in_conference){ + if (call->params->in_conference){ /*transform the graph to connect it to the conference filter */ mute=stream->dir==SalStreamRecvOnly; linphone_call_add_to_conf(call, mute); } - call->current_params.in_conference=call->params.in_conference; - call->current_params.low_bandwidth=call->params.low_bandwidth; + call->current_params->in_conference=call->params->in_conference; + call->current_params->low_bandwidth=call->params->low_bandwidth; }else ms_warning("No audio stream accepted ?"); } } @@ -2164,12 +2025,17 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna int used_pt=-1; char rtcp_tool[128]={0}; const SalStreamDescription *vstream; + MSFilter* source = NULL; + bool_t reused_preview = FALSE; snprintf(rtcp_tool,sizeof(rtcp_tool)-1,"%s-%s",linphone_core_get_user_agent_name(),linphone_core_get_user_agent_version()); /* shutdown preview */ if (lc->previewstream!=NULL) { - video_preview_stop(lc->previewstream); + + if( lc->video_conf.reuse_preview_source == FALSE) video_preview_stop(lc->previewstream); + else source = video_preview_stop_reuse_source(lc->previewstream); + lc->previewstream=NULL; } @@ -2186,11 +2052,13 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna MSWebCam *cam=lc->video_conf.device; bool_t is_inactive=FALSE; - call->current_params.video_codec = rtp_profile_get_payload(call->video_profile, used_pt); - call->current_params.has_video=TRUE; + call->current_params->video_codec = rtp_profile_get_payload(call->video_profile, used_pt); + call->current_params->has_video=TRUE; video_stream_enable_adaptive_bitrate_control(call->videostream, linphone_core_adaptive_rate_control_enabled(lc)); + media_stream_set_adaptive_bitrate_algorithm(&call->videostream->ms, + ms_qos_analyzer_algorithm_from_string(linphone_core_get_adaptive_rate_algorithm(lc))); video_stream_enable_adaptive_jittcomp(call->videostream, linphone_core_video_adaptive_jittcomp_enabled(lc)); if (lc->video_conf.preview_vsize.width!=0) video_stream_set_preview_size(call->videostream,lc->video_conf.preview_vsize); @@ -2242,15 +2110,30 @@ static void linphone_call_start_video_stream(LinphoneCall *call, const char *cna video_stream_set_device_rotation(call->videostream, lc->device_rotation); video_stream_set_rtcp_information(call->videostream, cname, rtcp_tool); video_stream_set_freeze_on_error(call->videostream, lp_config_get_int(lc->config, "video", "freeze_on_error", 0)); - video_stream_start(call->videostream, - call->video_profile, rtp_addr, vstream->rtp_port, - rtcp_addr, - linphone_core_rtcp_enabled(lc) ? (vstream->rtcp_port ? vstream->rtcp_port : vstream->rtp_port+1) : 0, - used_pt, linphone_core_get_video_jittcomp(lc), cam); + if( lc->video_conf.reuse_preview_source && source ){ + ms_message("video_stream_start_with_source kept: %p", source); + video_stream_start_with_source(call->videostream, + call->video_profile, rtp_addr, vstream->rtp_port, + rtcp_addr, + linphone_core_rtcp_enabled(lc) ? (vstream->rtcp_port ? vstream->rtcp_port : vstream->rtp_port+1) : 0, + used_pt, linphone_core_get_video_jittcomp(lc), cam, source); + reused_preview = TRUE; + } else { + video_stream_start(call->videostream, + call->video_profile, rtp_addr, vstream->rtp_port, + rtcp_addr, + linphone_core_rtcp_enabled(lc) ? (vstream->rtcp_port ? vstream->rtcp_port : vstream->rtp_port+1) : 0, + used_pt, linphone_core_get_video_jittcomp(lc), cam); + } } }else ms_warning("No video stream accepted."); }else{ - ms_warning("No valid video stream defined."); + ms_message("No valid video stream defined."); + } + if( reused_preview == FALSE && source != NULL ){ + /* destroy not-reused source filter */ + ms_warning("Video preview (%p) not reused: destroying it.", source); + ms_filter_destroy(source); } #endif } @@ -2264,8 +2147,8 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut const SalStreamDescription *vstream=sal_media_description_find_best_stream(call->resultdesc,SalVideo); #endif - call->current_params.audio_codec = NULL; - call->current_params.video_codec = NULL; + call->current_params->audio_codec = NULL; + call->current_params->video_codec = NULL; if ((call->audiostream == NULL) && (call->videostream == NULL)) { ms_fatal("start_media_stream() called without prior init !"); @@ -2285,7 +2168,7 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut if (call->audiostream!=NULL) { linphone_call_start_audio_stream(call,cname,all_inputs_muted,send_ringbacktone,use_arc); } - call->current_params.has_video=FALSE; + call->current_params->has_video=FALSE; if (call->videostream!=NULL) { if (call->audiostream) audio_stream_link_video(call->audiostream,call->videostream); linphone_call_start_video_stream(call,cname,all_inputs_muted); @@ -2295,7 +2178,7 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut call->playing_ringbacktone=send_ringbacktone; call->up_bw=linphone_core_get_upload_bandwidth(lc); - if (call->params.media_encryption==LinphoneMediaEncryptionZRTP) { + if (call->params->media_encryption==LinphoneMediaEncryptionZRTP) { OrtpZrtpParams params; memset(¶ms,0,sizeof(OrtpZrtpParams)); /*call->current_params.media_encryption will be set later when zrtp is activated*/ @@ -2311,7 +2194,7 @@ void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_mut } #endif }else{ - call->current_params.media_encryption=linphone_call_all_streams_encrypted(call) ? + call->current_params->media_encryption=linphone_call_all_streams_encrypted(call) ? LinphoneMediaEncryptionSRTP : LinphoneMediaEncryptionNone; } @@ -2424,7 +2307,7 @@ static void linphone_call_stop_audio_stream(LinphoneCall *call) { ms_filter_call_method(call->audiostream->ec,MS_ECHO_CANCELLER_GET_STATE_STRING,&state_str); if (state_str){ ms_message("Writing echo canceler state, %i bytes",(int)strlen(state_str)); - lp_config_set_string(call->core->config,"sound","ec_state",state_str); + lp_config_write_relative_file(call->core->config, EC_STATE_STORE, state_str); } } audio_stream_get_local_rtp_stats(call->audiostream,&call->log->local_stats); @@ -2434,7 +2317,7 @@ static void linphone_call_stop_audio_stream(LinphoneCall *call) { } audio_stream_stop(call->audiostream); call->audiostream=NULL; - call->current_params.audio_codec = NULL; + call->current_params->audio_codec = NULL; } } @@ -2450,7 +2333,7 @@ static void linphone_call_stop_video_stream(LinphoneCall *call) { linphone_call_log_fill_stats(call->log,(MediaStream*)call->videostream); video_stream_stop(call->videostream); call->videostream=NULL; - call->current_params.video_codec = NULL; + call->current_params->video_codec = NULL; } #endif } @@ -2761,26 +2644,39 @@ uint64_t linphone_call_stats_get_late_packets_cumulative_number(const LinphoneCa } /** - * Enable recording of the call (voice-only). - * This function must be used before the call parameters are assigned to the call. - * The call recording can be started and paused after the call is established with - * linphone_call_start_recording() and linphone_call_pause_recording(). - * @param cp the call parameters - * @param path path and filename of the file where audio is written. -**/ -void linphone_call_params_set_record_file(LinphoneCallParams *cp, const char *path){ - if (cp->record_file){ - ms_free(cp->record_file); - cp->record_file=NULL; - } - if (path) cp->record_file=ms_strdup(path); + * Get the bandwidth measurement of the received stream, expressed in kbit/s, including IP/UDP/RTP headers. + * @param[in] stats LinphoneCallStats object + * @return The bandwidth measurement of the received stream in kbit/s. + */ +float linphone_call_stats_get_download_bandwidth(const LinphoneCallStats *stats) { + return stats->download_bandwidth; } /** - * Retrieves the path for the audio recoding of the call. -**/ -const char *linphone_call_params_get_record_file(const LinphoneCallParams *cp){ - return cp->record_file; + * Get the bandwidth measurement of the sent stream, expressed in kbit/s, including IP/UDP/RTP headers. + * @param[in] stats LinphoneCallStats object + * @return The bandwidth measurement of the sent stream in kbit/s. + */ +float linphone_call_stats_get_upload_bandwidth(const LinphoneCallStats *stats) { + return stats->upload_bandwidth; +} + +/** + * Get the state of ICE processing. + * @param[in] stats LinphoneCallStats object + * @return The state of ICE processing. + */ +LinphoneIceState linphone_call_stats_get_ice_state(const LinphoneCallStats *stats) { + return stats->ice_state; +} + +/** + * Get the state of uPnP processing. + * @param[in] stats LinphoneCallStats object + * @return The state of uPnP processing. + */ +LinphoneUpnpState linphone_call_stats_get_upnp_state(const LinphoneCallStats *stats) { + return stats->upnp_state; } /** @@ -2788,11 +2684,11 @@ const char *linphone_call_params_get_record_file(const LinphoneCallParams *cp){ * The output file where audio is recorded must be previously specified with linphone_call_params_set_record_file(). **/ void linphone_call_start_recording(LinphoneCall *call){ - if (!call->params.record_file){ + if (!call->params->record_file){ ms_error("linphone_call_start_recording(): no output file specified. Use linphone_call_params_set_record_file()."); return; } - if (call->audiostream && !call->params.in_conference){ + if (call->audiostream && !call->params->in_conference){ audio_stream_mixed_record_start(call->audiostream); } call->record_active=TRUE; @@ -2802,7 +2698,7 @@ void linphone_call_start_recording(LinphoneCall *call){ * Stop call recording. **/ void linphone_call_stop_recording(LinphoneCall *call){ - if (call->audiostream && !call->params.in_conference){ + if (call->audiostream && !call->params->in_conference){ audio_stream_mixed_record_stop(call->audiostream); } call->record_active=FALSE; @@ -2835,8 +2731,7 @@ static void linphone_core_disconnected(LinphoneCore *lc, LinphoneCall *call){ if (from) ms_free(from); ms_message("On call [%p]: %s",call,temp); - if (lc->vtable.display_warning!=NULL) - lc->vtable.display_warning(lc,temp); + linphone_core_notify_display_warning(lc,temp); linphone_core_terminate_call(lc,call); linphone_core_play_named_tone(lc,LinphoneToneCallLost); } @@ -2847,17 +2742,16 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){ int ping_time; if (evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) { - LinphoneCallParams params; - _linphone_call_params_copy(¶ms,&call->current_params); - if (call->params.media_encryption == LinphoneMediaEncryptionZRTP) { + LinphoneCallParams *params = linphone_call_params_copy(call->current_params); + if (call->params->media_encryption == LinphoneMediaEncryptionZRTP) { /* preserve media encryption param because at that time ZRTP negociation may still be ongoing*/ - params.media_encryption=call->params.media_encryption; + params->media_encryption=call->params->media_encryption; } switch (ice_session_state(call->ice_session)) { case IS_Completed: ice_session_select_candidates(call->ice_session); if (ice_session_role(call->ice_session) == IR_Controlling) { - linphone_core_update_call(call->core, call, ¶ms); + linphone_core_update_call(call->core, call, params); } break; case IS_Failed: @@ -2865,7 +2759,7 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){ ice_session_select_candidates(call->ice_session); if (ice_session_role(call->ice_session) == IR_Controlling) { /* At least one ICE session has succeeded, so perform a call update. */ - linphone_core_update_call(call->core, call, ¶ms); + linphone_core_update_call(call->core, call, params); } } break; @@ -2873,6 +2767,7 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){ break; } linphone_core_update_ice_state_in_call_stats(call); + linphone_call_params_unref(params); } else if (evt == ORTP_EVENT_ICE_GATHERING_FINISHED) { if (evd->info.ice_processing_successful==TRUE) { @@ -2892,7 +2787,7 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){ linphone_core_start_update_call(call->core, call); break; case LinphoneCallUpdatedByRemote: - linphone_core_start_accept_call_update(call->core, call); + linphone_core_start_accept_call_update(call->core, call,call->prevstate,linphone_call_state_to_string(call->prevstate)); break; case LinphoneCallOutgoingInit: linphone_call_stop_media_streams_for_ice_gathering(call); @@ -2907,13 +2802,13 @@ static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){ } } else if (evt == ORTP_EVENT_ICE_LOSING_PAIRS_COMPLETED) { if (call->state==LinphoneCallUpdatedByRemote){ - linphone_core_start_accept_call_update(call->core, call); + linphone_core_start_accept_call_update(call->core, call,call->prevstate,linphone_call_state_to_string(call->prevstate)); linphone_core_update_ice_state_in_call_stats(call); } } else if (evt == ORTP_EVENT_ICE_RESTART_NEEDED) { ice_session_restart(call->ice_session); ice_session_set_role(call->ice_session, IR_Controlling); - linphone_core_update_call(call->core, call, &call->current_params); + linphone_core_update_call(call->core, call, call->current_params); } } @@ -2958,8 +2853,7 @@ void linphone_call_notify_stats_updated(LinphoneCall *call, int stream_index){ LinphoneCore *lc=call->core; if (stats->updated){ linphone_reporting_on_rtcp_update(call, stream_index); - if (lc->vtable.call_stats_updated) - lc->vtable.call_stats_updated(lc, call, stats); + linphone_core_notify_call_stats_updated(lc, call, stats); stats->updated = 0; } } @@ -3054,11 +2948,10 @@ void linphone_call_log_completed(LinphoneCall *call){ info=ortp_strdup_printf(ngettext("You have missed %i call.", "You have missed %i calls.", lc->missed_calls), lc->missed_calls); - if (lc->vtable.display_status!=NULL) - lc->vtable.display_status(lc,info); + linphone_core_notify_display_status(lc,info); ms_free(info); } - lc->call_logs=ms_list_prepend(lc->call_logs,(void *)call->log); + lc->call_logs=ms_list_prepend(lc->call_logs,linphone_call_log_ref(call->log)); if (ms_list_size(lc->call_logs)>lc->max_call_logs){ MSList *elem,*prevelem=NULL; /*find the last element*/ @@ -3066,12 +2959,10 @@ void linphone_call_log_completed(LinphoneCall *call){ prevelem=elem; } elem=prevelem; - linphone_call_log_destroy((LinphoneCallLog*)elem->data); + linphone_call_log_unref((LinphoneCallLog*)elem->data); lc->call_logs=ms_list_remove_link(lc->call_logs,elem); } - if (lc->vtable.call_log_updated!=NULL){ - lc->vtable.call_log_updated(lc,call->log); - } + linphone_core_notify_call_log_updated(lc,call->log); call_logs_write_to_config_file(lc); } @@ -3090,13 +2981,12 @@ void linphone_call_set_transfer_state(LinphoneCall* call, LinphoneCallState stat ,linphone_call_state_to_string(call->transfer_state) ,linphone_call_state_to_string(state)); call->transfer_state = state; - if (lc->vtable.transfer_state_changed) - lc->vtable.transfer_state_changed(lc, call, state); + linphone_core_notify_transfer_state_changed(lc, call, state); } } bool_t linphone_call_is_in_conference(const LinphoneCall *call) { - return call->params.in_conference; + return call->params->in_conference; } /** @@ -3130,7 +3020,7 @@ void linphone_call_zoom_video(LinphoneCall* call, float zoom_factor, float* cx, zoom[0] = zoom_factor; zoom[1] = *cx; zoom[2] = *cy; - ms_filter_call_method(vstream->output, MS_VIDEO_DISPLAY_ZOOM, &zoom); + ms_filter_call_method(vstream->output, MS_VIDEO_DISPLAY_ZOOM, &zoom); }else ms_warning("Could not apply zoom: video output wasn't activated."); } @@ -3140,7 +3030,7 @@ static LinphoneAddress *get_fixed_contact(LinphoneCore *lc, LinphoneCall *call , const char *localip=call->localip; /* first use user's supplied ip address if asked*/ - if (linphone_core_get_firewall_policy(lc)==LinphonePolicyUseNatAddress){ + if (_linphone_core_get_firewall_policy(lc)==LinphonePolicyUseNatAddress){ ctt=linphone_core_get_primary_contact_parsed(lc); linphone_address_set_domain(ctt,linphone_core_get_nat_address_resolved(lc)); ret=ctt; @@ -3186,3 +3076,16 @@ void linphone_call_set_contact_op(LinphoneCall* call) { linphone_address_destroy(contact); } } + +LinphonePlayer *linphone_call_get_player(LinphoneCall *call){ + if (call->player==NULL) + call->player=linphone_call_build_player(call); + return call->player; +} + +void linphone_call_set_new_params(LinphoneCall *call, const LinphoneCallParams *params){ + LinphoneCallParams *cp=NULL; + if (params) cp=linphone_call_params_copy(params); + if (call->params) linphone_call_params_unref(call->params); + call->params=cp; +} diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 8e5e06172..1cb00d513 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -17,8 +17,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#define _GNU_SOURCE - #include "linphonecore.h" #include "sipsetup.h" #include "lpconfig.h" @@ -42,7 +40,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifdef HAVE_CONFIG_H #include "config.h" -#include "liblinphone_gitversion.h" +#ifndef ANDROID /*on Android LIBLINPHONE version is passed from root Makefile*/ + #include "liblinphone_gitversion.h" +#endif #else #ifndef LIBLINPHONE_GIT_VERSION #define LIBLINPHONE_GIT_VERSION "unknown" @@ -64,6 +64,7 @@ static const char *liblinphone_version= LIBLINPHONE_VERSION #endif ; +static bool_t liblinphone_serialize_logs = FALSE; static void set_network_reachable(LinphoneCore* lc,bool_t isReachable, time_t curtime); static void linphone_core_run_hooks(LinphoneCore *lc); static void linphone_core_free_hooks(LinphoneCore *lc); @@ -75,10 +76,10 @@ static void linphone_core_free_hooks(LinphoneCore *lc); const char *linphone_core_get_nat_address_resolved(LinphoneCore *lc); static void toggle_video_preview(LinphoneCore *lc, bool_t val); -#ifdef WINAPI_FAMILY_PHONE_APP -#define SOUNDS_PREFIX "Assets/Sounds/" -#else +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) #define SOUNDS_PREFIX +#else +#define SOUNDS_PREFIX "Assets/Sounds/" #endif /* relative path where is stored local ring*/ #define LOCAL_RING SOUNDS_PREFIX "rings/oldphone.wav" @@ -101,305 +102,6 @@ int lc_callback_obj_invoke(LCCallbackObj *obj, LinphoneCore *lc){ } -/*prevent a gcc bug with %c*/ -static size_t my_strftime(char *s, size_t max, const char *fmt, const struct tm *tm){ - return strftime(s, max, fmt, tm); -} - -static void set_call_log_date(LinphoneCallLog *cl, time_t start_time){ - struct tm loctime; -#ifdef WIN32 -#if !defined(_WIN32_WCE) - loctime=*localtime(&start_time); - /*FIXME*/ -#endif /*_WIN32_WCE*/ -#else - localtime_r(&start_time,&loctime); -#endif - my_strftime(cl->start_date,sizeof(cl->start_date),"%c",&loctime); -} - -LinphoneCallLog * linphone_call_log_new(LinphoneCall *call, LinphoneAddress *from, LinphoneAddress *to){ - LinphoneCallLog *cl=ms_new0(LinphoneCallLog,1); - cl->dir=call->dir; - cl->start_date_time=time(NULL); - set_call_log_date(cl,cl->start_date_time); - cl->from=from; - cl->to=to; - cl->status=LinphoneCallAborted; /*default status*/ - cl->quality=-1; - - cl->reporting.reports[LINPHONE_CALL_STATS_AUDIO]=linphone_reporting_new(); - cl->reporting.reports[LINPHONE_CALL_STATS_VIDEO]=linphone_reporting_new(); - return cl; -} - -void call_logs_write_to_config_file(LinphoneCore *lc){ - MSList *elem; - char logsection[32]; - int i; - char *tmp; - LpConfig *cfg=lc->config; - - if (linphone_core_get_global_state (lc)==LinphoneGlobalStartup) return; - - for(i=0,elem=lc->call_logs;elem!=NULL;elem=elem->next,++i){ - LinphoneCallLog *cl=(LinphoneCallLog*)elem->data; - snprintf(logsection,sizeof(logsection),"call_log_%i",i); - lp_config_clean_section(cfg,logsection); - lp_config_set_int(cfg,logsection,"dir",cl->dir); - lp_config_set_int(cfg,logsection,"status",cl->status); - tmp=linphone_address_as_string(cl->from); - lp_config_set_string(cfg,logsection,"from",tmp); - ms_free(tmp); - tmp=linphone_address_as_string(cl->to); - lp_config_set_string(cfg,logsection,"to",tmp); - ms_free(tmp); - if (cl->start_date_time) - lp_config_set_int64(cfg,logsection,"start_date_time",(int64_t)cl->start_date_time); - else lp_config_set_string(cfg,logsection,"start_date",cl->start_date); - lp_config_set_int(cfg,logsection,"duration",cl->duration); - if (cl->refkey) lp_config_set_string(cfg,logsection,"refkey",cl->refkey); - lp_config_set_float(cfg,logsection,"quality",cl->quality); - lp_config_set_int(cfg,logsection,"video_enabled", cl->video_enabled); - lp_config_set_string(cfg,logsection,"call_id",cl->call_id); - } - for(;imax_call_logs;++i){ - snprintf(logsection,sizeof(logsection),"call_log_%i",i); - lp_config_clean_section(cfg,logsection); - } -} - -static time_t string_to_time(const char *date){ -#ifndef WIN32 - struct tm tmtime={0}; - strptime(date,"%c",&tmtime); - return mktime(&tmtime); -#else - return 0; -#endif -} - -static void call_logs_read_from_config_file(LinphoneCore *lc){ - char logsection[32]; - int i; - const char *tmp; - uint64_t sec; - LpConfig *cfg=lc->config; - for(i=0;;++i){ - snprintf(logsection,sizeof(logsection),"call_log_%i",i); - if (lp_config_has_section(cfg,logsection)){ - LinphoneCallLog *cl=ms_new0(LinphoneCallLog,1); - cl->dir=lp_config_get_int(cfg,logsection,"dir",0); - cl->status=lp_config_get_int(cfg,logsection,"status",0); - tmp=lp_config_get_string(cfg,logsection,"from",NULL); - if (tmp) cl->from=linphone_address_new(tmp); - tmp=lp_config_get_string(cfg,logsection,"to",NULL); - if (tmp) cl->to=linphone_address_new(tmp); - sec=lp_config_get_int64(cfg,logsection,"start_date_time",0); - if (sec) { - /*new call log format with date expressed in seconds */ - cl->start_date_time=(time_t)sec; - set_call_log_date(cl,cl->start_date_time); - }else{ - tmp=lp_config_get_string(cfg,logsection,"start_date",NULL); - if (tmp) { - strncpy(cl->start_date,tmp,sizeof(cl->start_date)); - cl->start_date_time=string_to_time(cl->start_date); - } - } - cl->duration=lp_config_get_int(cfg,logsection,"duration",0); - tmp=lp_config_get_string(cfg,logsection,"refkey",NULL); - if (tmp) cl->refkey=ms_strdup(tmp); - cl->quality=lp_config_get_float(cfg,logsection,"quality",-1); - cl->video_enabled=lp_config_get_int(cfg,logsection,"video_enabled",0); - tmp=lp_config_get_string(cfg,logsection,"call_id",NULL); - if (tmp) cl->call_id=ms_strdup(tmp); - lc->call_logs=ms_list_append(lc->call_logs,cl); - }else break; - } -} - - - -/** - * @addtogroup call_logs - * @{ -**/ - -/** - * Returns a human readable string describing the call. - * - * @note: the returned char* must be freed by the application (use ms_free()). -**/ -char * linphone_call_log_to_str(LinphoneCallLog *cl){ - char *status; - char *tmp; - char *from=linphone_address_as_string (cl->from); - char *to=linphone_address_as_string (cl->to); - switch(cl->status){ - case LinphoneCallAborted: - status=_("aborted"); - break; - case LinphoneCallSuccess: - status=_("completed"); - break; - case LinphoneCallMissed: - status=_("missed"); - break; - default: - status="unknown"; - } - tmp=ortp_strdup_printf(_("%s at %s\nFrom: %s\nTo: %s\nStatus: %s\nDuration: %i mn %i sec\n"), - (cl->dir==LinphoneCallIncoming) ? _("Incoming call") : _("Outgoing call"), - cl->start_date, - from, - to, - status, - cl->duration/60, - cl->duration%60); - ms_free(from); - ms_free(to); - return tmp; -} - -/** - * Returns RTP statistics computed locally regarding the call. - * -**/ -const rtp_stats_t *linphone_call_log_get_local_stats(const LinphoneCallLog *cl){ - return &cl->local_stats; -} - -/** - * Returns RTP statistics computed by remote end and sent back via RTCP. - * - * @note Not implemented yet. -**/ -const rtp_stats_t *linphone_call_log_get_remote_stats(const LinphoneCallLog *cl){ - return &cl->remote_stats; -} - -const char *linphone_call_log_get_call_id(const LinphoneCallLog *cl){ - return cl->call_id; -} - -/** - * Assign a user pointer to the call log. -**/ -void linphone_call_log_set_user_pointer(LinphoneCallLog *cl, void *up){ - cl->user_pointer=up; -} - -/** - * Returns the user pointer associated with the call log. -**/ -void *linphone_call_log_get_user_pointer(const LinphoneCallLog *cl){ - return cl->user_pointer; -} - - - -/** - * Associate a persistent reference key to the call log. - * - * The reference key can be for example an id to an external database. - * It is stored in the config file, thus can survive to process exits/restarts. - * -**/ -void linphone_call_log_set_ref_key(LinphoneCallLog *cl, const char *refkey){ - if (cl->refkey!=NULL){ - ms_free(cl->refkey); - cl->refkey=NULL; - } - if (refkey) cl->refkey=ms_strdup(refkey); -} - -/** - * Get the persistent reference key associated to the call log. - * - * The reference key can be for example an id to an external database. - * It is stored in the config file, thus can survive to process exits/restarts. - * -**/ -const char *linphone_call_log_get_ref_key(const LinphoneCallLog *cl){ - return cl->refkey; -} - -/** - * Returns origin (ie from) address of the call. -**/ -LinphoneAddress *linphone_call_log_get_from(LinphoneCallLog *cl){ - return cl->from; -} - -/** - * Returns destination address (ie to) of the call. -**/ -LinphoneAddress *linphone_call_log_get_to(LinphoneCallLog *cl){ - return cl->to; -} - -/** - * Returns remote address (that is from or to depending on call direction). -**/ -LinphoneAddress *linphone_call_log_get_remote_address(LinphoneCallLog *cl){ - return (cl->dir == LinphoneCallIncoming) ? cl->from : cl->to; -} - -/** - * Returns the direction of the call. -**/ -LinphoneCallDir linphone_call_log_get_dir(LinphoneCallLog *cl){ - return cl->dir; -} - -/** - * Returns the status of the call. -**/ -LinphoneCallStatus linphone_call_log_get_status(LinphoneCallLog *cl){ - return cl->status; -} - -/** - * Returns the start date of the call, expressed as a POSIX time_t. -**/ -time_t linphone_call_log_get_start_date(LinphoneCallLog *cl){ - return cl->start_date_time; -} - -/** - * Returns duration of the call. -**/ -int linphone_call_log_get_duration(LinphoneCallLog *cl){ - return cl->duration; -} - -/** - * Returns overall quality indication of the call. -**/ -float linphone_call_log_get_quality(LinphoneCallLog *cl){ - return cl->quality; -} -/** - * return true if video was enabled at the end of the call - */ -bool_t linphone_call_log_video_enabled(LinphoneCallLog *cl) { - return cl->video_enabled; -} -/** @} */ - -void linphone_call_log_destroy(LinphoneCallLog *cl){ - if (cl->from!=NULL) linphone_address_destroy(cl->from); - if (cl->to!=NULL) linphone_address_destroy(cl->to); - if (cl->refkey!=NULL) ms_free(cl->refkey); - if (cl->call_id) ms_free(cl->call_id); - if (cl->reporting.reports[LINPHONE_CALL_STATS_AUDIO]!=NULL) linphone_reporting_destroy(cl->reporting.reports[LINPHONE_CALL_STATS_AUDIO]); - if (cl->reporting.reports[LINPHONE_CALL_STATS_VIDEO]!=NULL) linphone_reporting_destroy(cl->reporting.reports[LINPHONE_CALL_STATS_VIDEO]); - - ms_free(cl); -} - /** * Returns TRUE if the LinphoneCall asked to autoanswer * @@ -480,11 +182,15 @@ void linphone_core_enable_logs_with_cb(OrtpLogFunc logfunc){ * @ingroup misc * @deprecated Use #linphone_core_set_log_level instead. **/ -void linphone_core_disable_logs(){ +void linphone_core_disable_logs(void){ ortp_set_log_level_mask(ORTP_ERROR|ORTP_FATAL); sal_disable_logs(); } +void linphone_core_serialize_logs(void) { + liblinphone_serialize_logs = TRUE; +} + static void net_config_read (LinphoneCore *lc) { @@ -722,6 +428,7 @@ static void sip_config_read(LinphoneCore *lc) LinphoneProxyConfig *cfg=linphone_proxy_config_new_from_config_file(lc,i); if (cfg!=NULL){ linphone_core_add_proxy_config(lc,cfg); + linphone_proxy_config_unref(cfg); }else{ break; } @@ -759,6 +466,7 @@ static void sip_config_read(LinphoneCore *lc) sal_enable_sip_update_method(lc->sal,lp_config_get_int(lc->config,"sip","sip_update",1)); lc->sip_conf.vfu_with_info=lp_config_get_int(lc->config,"sip","vfu_with_info",1); linphone_core_set_sip_transport_timeout(lc, lp_config_get_int(lc->config, "sip", "transport_timeout", 63000)); + sal_set_supported_tags(lc->sal,lp_config_get_string(lc->config,"sip","supported","replaces, outbound")); } static void rtp_config_read(LinphoneCore *lc) @@ -801,6 +509,7 @@ static void rtp_config_read(LinphoneCore *lc) adaptive_jitt_comp_enabled = lp_config_get_int(lc->config, "rtp", "video_adaptive_jitt_comp_enabled", TRUE); linphone_core_enable_video_adaptive_jittcomp(lc, adaptive_jitt_comp_enabled); lc->rtp_conf.disable_upnp = lp_config_get_int(lc->config, "rtp", "disable_upnp", FALSE); + linphone_core_set_avpf_mode(lc,lp_config_get_int(lc->config,"rtp","avpf",0)); } static PayloadType * find_payload(RtpProfile *prof, const char *mime_type, int clock_rate, int channels, const char *recv_fmtp){ @@ -897,7 +606,7 @@ static int codec_compare(const PayloadType *a, const PayloadType *b){ rb=find_codec_rank(b->mime_type,b->clock_rate); if (ra>rb) return 1; if (raconfig,"video","size","cif")); - + linphone_core_set_preview_video_size_by_name(lc, lp_config_get_string(lc->config,"video","preview_size",NULL)); - + linphone_core_set_preferred_framerate(lc,lp_config_get_float(lc->config,"video","framerate",0)); #ifdef VIDEO_ENABLED @@ -1014,12 +723,14 @@ static void video_config_read(LinphoneCore *lc){ capture=lp_config_get_int(lc->config,"video","capture",1); display=lp_config_get_int(lc->config,"video","display",1); self_view=lp_config_get_int(lc->config,"video","self_view",1); + reuse_source=lp_config_get_int(lc->config,"video","reuse_source",0); vpol.automatically_initiate=lp_config_get_int(lc->config,"video","automatically_initiate",automatic_video); vpol.automatically_accept=lp_config_get_int(lc->config,"video","automatically_accept",automatic_video); linphone_core_enable_video_capture(lc, capture); linphone_core_enable_video_display(lc, display); linphone_core_enable_video_preview(lc,lp_config_get_int(lc->config,"video","show_local",0)); linphone_core_enable_self_view(lc,self_view); + linphone_core_enable_video_source_reuse(lc, reuse_source); linphone_core_set_video_policy(lc,&vpol); #endif } @@ -1080,6 +791,28 @@ bool_t linphone_core_adaptive_rate_control_enabled(const LinphoneCore *lc){ return lp_config_get_int(lc->config,"net","adaptive_rate_control",TRUE); } +/** + * Sets adaptive rate algorithm. It will be used for each new calls starting from + * now. Calls already started will not be updated. + * + * @ingroup media_parameters + * +**/ +void linphone_core_set_adaptive_rate_algorithm(LinphoneCore *lc, const char* algorithm){ + lp_config_set_string(lc->config,"net","adaptive_rate_algorithm",algorithm); +} + +/** + * Returns which adaptive rate algorithm is currently configured for future calls. + * + * @ingroup media_parameters + * + * See linphone_core_set_adaptive_rate_algorithm(). +**/ +const char * linphone_core_get_adaptive_rate_algorithm(const LinphoneCore *lc){ + return lp_config_get_string(lc->config, "net", "adaptive_rate_algorithm", "Simple"); +} + bool_t linphone_core_rtcp_enabled(const LinphoneCore *lc){ return lp_config_get_int(lc->config,"rtp","rtcp_enabled",TRUE); } @@ -1264,9 +997,7 @@ static void linphone_core_free_payload_types(LinphoneCore *lc){ void linphone_core_set_state(LinphoneCore *lc, LinphoneGlobalState gstate, const char *message){ lc->state=gstate; - if (lc->vtable.global_state_changed){ - lc->vtable.global_state_changed(lc,gstate,message); - } + linphone_core_notify_global_state_changed(lc,gstate,message); } static void misc_config_read(LinphoneCore *lc) { @@ -1299,18 +1030,18 @@ static void linphone_core_start(LinphoneCore * lc) { ui_config_read(lc); #ifdef TUNNEL_ENABLED lc->tunnel=linphone_core_tunnel_new(lc); - if (lc->tunnel) linphone_tunnel_configure(lc->tunnel); + if (lc->tunnel) { + linphone_tunnel_configure(lc->tunnel); + } #endif - if (lc->vtable.display_status) - lc->vtable.display_status(lc,_("Ready")); + linphone_core_notify_display_status(lc,_("Ready")); lc->auto_net_state_mon=lc->sip_conf.auto_net_state_mon; linphone_core_set_state(lc,LinphoneGlobalOn,"Ready"); } void linphone_configuring_terminated(LinphoneCore *lc, LinphoneConfiguringState state, const char *message) { - if (lc->vtable.configuring_status) - lc->vtable.configuring_status(lc, state, message); + linphone_core_notify_configuring_status(lc, state, message); if (state == LinphoneConfiguringSuccessful) { if (linphone_core_is_provisioning_transient(lc) == TRUE) @@ -1323,16 +1054,21 @@ void linphone_configuring_terminated(LinphoneCore *lc, LinphoneConfiguringState static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtable, LpConfig *config, void * userdata) { const char *remote_provisioning_uri = NULL; + LinphoneCoreVTable* local_vtable= linphone_vtable_new(); ms_message("Initializing LinphoneCore %s", linphone_core_get_version()); memset (lc, 0, sizeof (LinphoneCore)); lc->config=lp_config_ref(config); lc->data=userdata; lc->ringstream_autorelease=TRUE; - memcpy(&lc->vtable,vtable,sizeof(LinphoneCoreVTable)); + memcpy(local_vtable,vtable,sizeof(LinphoneCoreVTable)); + lc->vtables=ms_list_append(lc->vtables,local_vtable); linphone_core_set_state(lc,LinphoneGlobalStartup,"Starting up"); ortp_init(); + if (liblinphone_serialize_logs == TRUE) { + ortp_set_log_thread_id(ortp_thread_self()); + } lc->dyn_pt=96; lc->default_profile=rtp_profile_new("default profile"); linphone_core_assign_payload_type(lc,&payload_type_pcmu8000,0,NULL); @@ -1419,7 +1155,7 @@ static void linphone_core_init(LinphoneCore * lc, const LinphoneCoreVTable *vtab remote_provisioning_uri = linphone_core_get_provisioning_uri(lc); if (remote_provisioning_uri == NULL) { linphone_configuring_terminated(lc, LinphoneConfiguringSkipped, NULL); - } // else linphone_core_start will be called after the remote provisioining (see linphone_core_iterate) + } // else linphone_core_start will be called after the remote provisioning (see linphone_core_iterate) } /** @@ -1460,6 +1196,8 @@ LinphoneCore *linphone_core_new_with_config(const LinphoneCoreVTable *vtable, st /** * Returns the list of available audio codecs. + * @param[in] lc The LinphoneCore object + * @return \mslist{PayloadType} * * This list is unmodifiable. The ->data field of the MSList points a PayloadType * structure holding the codec information. @@ -1474,6 +1212,8 @@ const MSList *linphone_core_get_audio_codecs(const LinphoneCore *lc) /** * Returns the list of available video codecs. + * @param[in] lc The LinphoneCore object + * @return \mslist{PayloadType} * * This list is unmodifiable. The ->data field of the MSList points a PayloadType * structure holding the codec information. @@ -1512,44 +1252,6 @@ int linphone_core_set_primary_contact(LinphoneCore *lc, const char *contact) } -/*Returns the local ip that routes to the internet, or guessed by other special means (upnp)*/ -/*result must be an array of chars at least LINPHONE_IPADDR_SIZE */ -void linphone_core_get_local_ip(LinphoneCore *lc, int af, char *result){ - const char *ip; - if (linphone_core_get_firewall_policy(lc)==LinphonePolicyUseNatAddress - && (ip=linphone_core_get_nat_address_resolved(lc))!=NULL){ - strncpy(result,ip,LINPHONE_IPADDR_SIZE); - return; - } -#ifdef BUILD_UPNP - else if (lc->upnp != NULL && linphone_core_get_firewall_policy(lc)==LinphonePolicyUseUpnp && - linphone_upnp_context_get_state(lc->upnp) == LinphoneUpnpStateOk) { - ip = linphone_upnp_context_get_external_ipaddress(lc->upnp); - strncpy(result,ip,LINPHONE_IPADDR_SIZE); - return; - } -#endif //BUILD_UPNP - if (af==AF_UNSPEC){ - if (linphone_core_ipv6_enabled(lc)){ - bool_t has_ipv6; - has_ipv6=linphone_core_get_local_ip_for(AF_INET6,NULL,result)==0; - if (strcmp(result,"::1")!=0) - return; /*this machine has real ipv6 connectivity*/ - if (linphone_core_get_local_ip_for(AF_INET,NULL,result)==0 && strcmp(result,"127.0.0.1")!=0) - return; /*this machine has only ipv4 connectivity*/ - if (has_ipv6){ - /*this machine has only local loopback for both ipv4 and ipv6, so prefer ipv6*/ - strncpy(result,"::1",LINPHONE_IPADDR_SIZE); - return; - } - } - /*in all other cases use IPv4*/ - af=AF_INET; - } - if (linphone_core_get_local_ip_for(af,NULL,result)==0) - return; -} - static void update_primary_contact(LinphoneCore *lc){ char *guessed=NULL; char tmp[LINPHONE_IPADDR_SIZE]; @@ -1564,7 +1266,7 @@ static void update_primary_contact(LinphoneCore *lc){ ms_error("Could not parse identity contact !"); url=linphone_address_new("sip:unknown@unkwownhost"); } - linphone_core_get_local_ip(lc, AF_UNSPEC, tmp); + linphone_core_get_local_ip(lc, AF_UNSPEC, NULL, tmp); if (strcmp(tmp,"127.0.0.1")==0 || strcmp(tmp,"::1")==0 ){ ms_warning("Local loopback network only !"); lc->sip_conf.loopback_only=TRUE; @@ -1634,6 +1336,9 @@ LinphoneAddress *linphone_core_get_primary_contact_parsed(LinphoneCore *lc){ /** * Sets the list of audio codecs. + * @param[in] lc The LinphoneCore object + * @param[in] codecs \mslist{PayloadType} + * @return 0 * * @ingroup media_parameters * The list is taken by the LinphoneCore thus the application should not free it. @@ -1649,6 +1354,9 @@ int linphone_core_set_audio_codecs(LinphoneCore *lc, MSList *codecs) /** * Sets the list of video codecs. + * @param[in] lc The LinphoneCore object + * @param[in] codecs \mslist{PayloadType} + * @return 0 * * @ingroup media_parameters * The list is taken by the LinphoneCore thus the application should not free it. @@ -1766,24 +1474,53 @@ bool_t linphone_core_get_rtp_no_xmit_on_audio_mute(const LinphoneCore *lc){ return lc->rtp_conf.rtp_no_xmit_on_audio_mute; } +static void apply_jitter_value(LinphoneCore *lc, int value, MSFormatType stype){ + LinphoneCall *call; + MSList *it; + for (it=lc->calls;it!=NULL;it=it->next){ + MediaStream *ms; + call=(LinphoneCall*)it->data; + ms = stype==MSAudio ? (MediaStream*)call->audiostream : (MediaStream*)call->videostream; + if (ms){ + RtpSession *s=ms->sessions.rtp_session; + if (s){ + if (value>0){ + ms_message("Jitter buffer size set to [%i] ms on call [%p]",value,call); + rtp_session_set_jitter_compensation(s,value); + rtp_session_enable_jitter_buffer(s,TRUE); + }else if (value==0){ + ms_warning("Jitter buffer is disabled per application request on call [%p]",call); + rtp_session_enable_jitter_buffer(s,FALSE); + } + } + } + } +} + /** * Sets the nominal audio jitter buffer size in milliseconds. + * The value takes effect immediately for all running and pending calls, if any. + * A value of 0 disables the jitter buffer. * * @ingroup media_parameters **/ void linphone_core_set_audio_jittcomp(LinphoneCore *lc, int value) { lc->rtp_conf.audio_jitt_comp=value; + apply_jitter_value(lc, value, MSAudio); } /** * Sets the nominal video jitter buffer size in milliseconds. + * The value takes effect immediately for all running and pending calls, if any. + * A value of 0 disables the jitter buffer. * * @ingroup media_parameters **/ void linphone_core_set_video_jittcomp(LinphoneCore *lc, int value) { lc->rtp_conf.video_jitt_comp=value; + apply_jitter_value(lc, value, MSVideo); } void linphone_core_set_rtp_no_xmit_on_audio_mute(LinphoneCore *lc,bool_t rtp_no_xmit_on_audio_mute){ @@ -1900,28 +1637,8 @@ int linphone_core_get_sip_port(LinphoneCore *lc) return tr.udp_port>0 ? tr.udp_port : (tr.tcp_port > 0 ? tr.tcp_port : tr.tls_port); } -#if !USE_BELLE_SIP static char _ua_name[64]="Linphone"; -static char _ua_version[64]=LINPHONE_VERSION; -#endif - -#if HAVE_EXOSIP_GET_VERSION && !USE_BELLESIP -extern const char *eXosip_get_version(); -#endif - -static void apply_user_agent(LinphoneCore *lc){ -#if !USE_BELLESIP /*default user agent is handled at sal level*/ - char ua_string[256]; - snprintf(ua_string,sizeof(ua_string)-1,"%s/%s (eXosip2/%s)",_ua_name,_ua_version, -#if HAVE_EXOSIP_GET_VERSION - eXosip_get_version() -#else - "unknown" -#endif - ); - if (lc->sal) sal_set_user_agent(lc->sal,ua_string); -#endif -} +static char _ua_version[64]=LIBLINPHONE_VERSION; /** * Sets the user agent string used in SIP messages. @@ -1929,27 +1646,15 @@ static void apply_user_agent(LinphoneCore *lc){ * @ingroup misc **/ void linphone_core_set_user_agent(LinphoneCore *lc, const char *name, const char *ver){ -#if USE_BELLESIP char ua_string[256]; snprintf(ua_string, sizeof(ua_string) - 1, "%s/%s", name?name:"", ver?ver:""); if (lc->sal) { sal_set_user_agent(lc->sal, ua_string); sal_append_stack_string_to_user_agent(lc->sal); } -#else - strncpy(_ua_name,name,sizeof(_ua_name)-1); - strncpy(_ua_version,ver,sizeof(_ua_version)); - apply_user_agent(lc); -#endif } const char *linphone_core_get_user_agent(LinphoneCore *lc){ -#if USE_BELLESIP return sal_get_user_agent(lc->sal); -#else - static char ua_buffer[255] = {0}; - snprintf(ua_buffer, "%s/%s", _ua_name, _ua_version, 254); - return ua_buffer; -#endif } const char *linphone_core_get_user_agent_name(void){ @@ -1963,8 +1668,7 @@ const char *linphone_core_get_user_agent_version(void){ static void transport_error(LinphoneCore *lc, const char* transport, int port){ char *msg=ortp_strdup_printf("Could not start %s transport on port %i, maybe this port is already used.",transport,port); ms_warning("%s",msg); - if (lc->vtable.display_warning) - lc->vtable.display_warning(lc,msg); + linphone_core_notify_display_warning(lc,msg); ms_free(msg); } @@ -2007,7 +1711,6 @@ static int apply_transports(LinphoneCore *lc){ } } } - apply_user_agent(lc); return 0; } @@ -2134,7 +1837,7 @@ static void monitor_network_state(LinphoneCore *lc, time_t curtime){ /* only do the network up checking every five seconds */ if (lc->network_last_check==0 || (curtime-lc->network_last_check)>=5){ - linphone_core_get_local_ip(lc,AF_UNSPEC,newip); + linphone_core_get_local_ip(lc,AF_UNSPEC,NULL,newip); if (strcmp(newip,"::1")!=0 && strcmp(newip,"127.0.0.1")!=0){ new_status=TRUE; }else new_status=FALSE; /*no network*/ @@ -2164,10 +1867,11 @@ static void proxy_update(LinphoneCore *lc){ for(elem=lc->sip_conf.deleted_proxies;elem!=NULL;elem=next){ LinphoneProxyConfig* cfg = (LinphoneProxyConfig*)elem->data; next=elem->next; - if (ms_time(NULL) - cfg->deletion_date > 5) { + if (ms_time(NULL) - cfg->deletion_date > 32) { lc->sip_conf.deleted_proxies =ms_list_remove_link(lc->sip_conf.deleted_proxies,elem); - ms_message("clearing proxy config for [%s]",linphone_proxy_config_get_addr(cfg)); - linphone_proxy_config_destroy(cfg); + ms_message("Proxy config for [%s] is definitely removed from core.",linphone_proxy_config_get_addr(cfg)); + _linphone_proxy_config_release_ops(cfg); + linphone_proxy_config_unref(cfg); } } } @@ -2177,8 +1881,7 @@ static void assign_buddy_info(LinphoneCore *lc, BuddyInfo *info){ if (lf!=NULL){ lf->info=info; ms_message("%s has a BuddyInfo assigned with image %p",info->sip_uri, info->image_data); - if (lc->vtable.buddy_info_updated) - lc->vtable.buddy_info_updated(lc,lf); + linphone_core_notify_buddy_info_updated(lc,lf); }else{ ms_warning("Could not any friend with uri %s",info->sip_uri); } @@ -2264,7 +1967,10 @@ void linphone_core_iterate(LinphoneCore *lc){ int elapsed; bool_t one_second_elapsed=FALSE; const char *remote_provisioning_uri = NULL; - + if (lc->network_reachable_to_be_notified) { + lc->network_reachable_to_be_notified=FALSE; + linphone_core_notify_network_reachable(lc,lc->network_reachable); + } if (linphone_core_get_global_state(lc) == LinphoneGlobalStartup) { if (sal_get_root_ca(lc->sal)) { belle_tls_verify_policy_t *tls_policy = belle_tls_verify_policy_new(); @@ -2272,8 +1978,7 @@ void linphone_core_iterate(LinphoneCore *lc){ belle_http_provider_set_tls_verify_policy(lc->http_provider, tls_policy); } - if (lc->vtable.display_status) - lc->vtable.display_status(lc, _("Configuring")); + linphone_core_notify_display_status(lc, _("Configuring")); linphone_core_set_state(lc, LinphoneGlobalConfiguring, "Configuring"); remote_provisioning_uri = linphone_core_get_provisioning_uri(lc); @@ -2362,7 +2067,7 @@ void linphone_core_iterate(LinphoneCore *lc){ #endif //BUILD_UPNP linphone_core_start_invite(lc,call, NULL); } - if (call->state==LinphoneCallIncomingReceived){ + if (call->state==LinphoneCallIncomingReceived || call->state==LinphoneCallIncomingEarlyMedia){ if (one_second_elapsed) ms_message("incoming call ringing for %i seconds",elapsed); if (elapsed>lc->sip_conf.inc_timeout){ LinphoneReason decline_reason; @@ -2406,6 +2111,10 @@ void linphone_core_iterate(LinphoneCore *lc){ lp_config_sync(lc->config); } } + + if (liblinphone_serialize_logs == TRUE) { + ortp_logv_flush(); + } } /** @@ -2434,11 +2143,9 @@ LinphoneAddress * linphone_core_interpret_url(LinphoneCore *lc, const char *url) if (*url=='\0') return NULL; if (is_enum(url,&enum_domain)){ - if (lc->vtable.display_status!=NULL) - lc->vtable.display_status(lc,_("Looking for telephone number destination...")); + linphone_core_notify_display_status(lc,_("Looking for telephone number destination...")); if (enum_lookup(enum_domain,&enumres)<0){ - if (lc->vtable.display_status!=NULL) - lc->vtable.display_status(lc,_("Could not resolve this number.")); + linphone_core_notify_display_status(lc,_("Could not resolve this number.")); ms_free(enum_domain); return NULL; } @@ -2535,7 +2242,7 @@ LinphoneCall * linphone_core_start_refered_call(LinphoneCore *lc, LinphoneCall * } if (!params){ - cp->has_video = call->current_params.has_video; /*start the call to refer-target with video enabled if original call had video*/ + cp->has_video = call->current_params->has_video; /*start the call to refer-target with video enabled if original call had video*/ } cp->referer=call; ms_message("Starting new call to refered address %s",call->refer_to); @@ -2721,13 +2428,11 @@ int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call, const Linph call->log->call_id=ms_strdup(sal_op_get_call_id(call->op)); /*must be known at that time*/ barmsg=ortp_strdup_printf("%s %s", _("Contacting"), real_url); - if (lc->vtable.display_status!=NULL) - lc->vtable.display_status(lc,barmsg); + linphone_core_notify_display_status(lc,barmsg); ms_free(barmsg); if (err<0){ - if (lc->vtable.display_status!=NULL) - lc->vtable.display_status(lc,_("Could not call")); + linphone_core_notify_display_status(lc,_("Could not call")); linphone_call_stop_media_streams(call); linphone_call_set_state(call,LinphoneCallError,"Call failed"); }else { @@ -2835,6 +2540,7 @@ void linphone_configure_op(LinphoneCore *lc, SalOp *op, const LinphoneAddress *d sal_op_set_to_address(op,dest); sal_op_set_from(op,identity); sal_op_set_sent_custom_header(op,headers); + sal_op_set_realm(op,linphone_proxy_config_get_realm(proxy)); if (with_contact && proxy && proxy->op){ const SalAddress *contact; if ((contact=sal_op_get_contact_address(proxy->op))){ @@ -2876,8 +2582,7 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const linphone_core_preempt_sound_resources(lc); if(!linphone_core_can_we_add_call(lc)){ - if (lc->vtable.display_warning) - lc->vtable.display_warning(lc,_("Sorry, we have reached the maximum number of simultaneous calls")); + linphone_core_notify_display_warning(lc,_("Sorry, we have reached the maximum number of simultaneous calls")); return NULL; } @@ -2888,6 +2593,9 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const from=linphone_proxy_config_get_identity(proxy); cp->avpf_enabled = linphone_proxy_config_avpf_enabled(proxy); cp->avpf_rr_interval = linphone_proxy_config_get_avpf_rr_interval(proxy) * 1000; + }else{ + cp->avpf_enabled=linphone_core_get_avpf_mode(lc)==LinphoneAVPFEnabled; + if (cp->avpf_enabled) cp->avpf_rr_interval=linphone_core_get_avpf_rr_interval(lc) * 1000; } /* if no proxy or no identity defined for this proxy, default to primary contact*/ @@ -2908,15 +2616,15 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const /* this call becomes now the current one*/ lc->current_call=call; linphone_call_set_state (call,LinphoneCallOutgoingInit,"Starting outgoing call"); - call->log->start_date_time=time(NULL); + call->log->start_date_time=ms_time(NULL); linphone_call_init_media_streams(call); - if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) { + if (_linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) { /* Defer the start of the call after the ICE gathering process. */ if (linphone_call_prepare_ice(call,FALSE)==1) defer=TRUE; } - else if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseUpnp) { + else if (_linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseUpnp) { #ifdef BUILD_UPNP if (linphone_core_update_upnp(lc,call)<0) { /* uPnP port mappings failed, proceed with the call anyway. */ @@ -3007,7 +2715,7 @@ int linphone_core_transfer_call_to_another(LinphoneCore *lc, LinphoneCall *call, return result; } -bool_t linphone_core_inc_invite_pending(LinphoneCore*lc){ +bool_t linphone_core_is_incoming_invite_pending(LinphoneCore*lc){ LinphoneCall *call = linphone_core_get_current_call(lc); if(call != NULL) { @@ -3036,8 +2744,7 @@ void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call){ if (md){ if (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md)){ sal_call_decline(call->op,SalReasonNotAcceptable,NULL); - linphone_call_stop_media_streams(call); - linphone_core_del_call(lc,call); + linphone_call_set_state_base(call, LinphoneCallError, NULL,TRUE); linphone_call_unref(call); return; } @@ -3049,9 +2756,8 @@ void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call){ linphone_address_destroy(from_parsed); barmesg=ortp_strdup_printf("%s %s%s",tmp,_("is contacting you"), (sal_call_autoanswer_asked(call->op)) ?_(" and asked autoanswer."):_(".")); - if (lc->vtable.show) lc->vtable.show(lc); - if (lc->vtable.display_status) - lc->vtable.display_status(lc,barmesg); + linphone_core_notify_show_interface(lc); + linphone_core_notify_display_status(lc,barmesg); /* play the ring if this is the only call*/ if (ms_list_size(lc->calls)==1){ @@ -3117,7 +2823,7 @@ int linphone_core_accept_early_media_with_params(LinphoneCore* lc, LinphoneCall* // if parameters are passed, update the media description if ( params ) { - _linphone_call_params_copy ( &call->params,params ); + linphone_call_set_new_params(call,params); linphone_call_make_local_media_description ( lc,call ); sal_call_set_local_media_description ( call->op,call->localdesc ); sal_op_set_sent_custom_header ( call->op,params->custom_headers ); @@ -3151,26 +2857,28 @@ int linphone_core_accept_early_media(LinphoneCore* lc, LinphoneCall* call){ int linphone_core_start_update_call(LinphoneCore *lc, LinphoneCall *call){ const char *subject; + bool_t no_user_consent=call->params->no_user_consent; - linphone_call_make_local_media_description(lc,call); + if (!no_user_consent) linphone_call_make_local_media_description(lc,call); #ifdef BUILD_UPNP if(call->upnp_session != NULL) { linphone_core_update_local_media_description_from_upnp(call->localdesc, call->upnp_session); } #endif //BUILD_UPNP - if (call->params.in_conference){ + if (call->params->in_conference){ subject="Conference"; - }else{ + }else if (!no_user_consent){ subject="Media change"; + }else{ + subject="Refreshing"; } - if (lc->vtable.display_status) - lc->vtable.display_status(lc,_("Modifying call parameters...")); + linphone_core_notify_display_status(lc,_("Modifying call parameters...")); sal_call_set_local_media_description (call->op,call->localdesc); if (call->dest_proxy && call->dest_proxy->op){ /*give a chance to update the contact address if connectivity has changed*/ sal_op_set_contact_address(call->op,sal_op_get_contact_address(call->dest_proxy->op)); }else sal_op_set_contact_address(call->op,NULL); - return sal_call_update(call->op,subject); + return sal_call_update(call->op,subject,no_user_consent); } /** @@ -3207,7 +2915,7 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho if (params!=NULL){ linphone_call_set_state(call,LinphoneCallUpdating,"Updating call"); #if defined(VIDEO_ENABLED) && defined(BUILD_UPNP) - has_video = call->params.has_video; + has_video = call->params->has_video; // Video removing if((call->videostream != NULL) && !params->has_video) { @@ -3220,8 +2928,7 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho } #endif /* defined(VIDEO_ENABLED) && defined(BUILD_UPNP) */ - - _linphone_call_params_copy(&call->params,params); + linphone_call_set_new_params(call,params); err=linphone_call_prepare_ice(call,FALSE); if (err==1) { ms_message("Defer call update to gather ICE candidates"); @@ -3230,7 +2937,7 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho #if defined(VIDEO_ENABLED) && defined(BUILD_UPNP) // Video adding - if (!has_video && call->params.has_video) { + if (!has_video && call->params->has_video) { if(call->upnp_session != NULL) { ms_message("Defer call update to add uPnP port mappings"); video_stream_prepare_video(call->videostream); @@ -3248,6 +2955,7 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho #ifdef VIDEO_ENABLED if ((call->videostream != NULL) && (call->state == LinphoneCallStreamsRunning)) { video_stream_set_sent_video_size(call->videostream,linphone_core_get_preferred_video_size(lc)); + video_stream_set_fps(call->videostream, linphone_core_get_preferred_framerate(lc)); if (call->camera_enabled && call->videostream->cam!=lc->video_conf.device){ video_stream_change_camera(call->videostream,lc->video_conf.device); }else video_stream_update_video_params(call->videostream); @@ -3281,7 +2989,7 @@ int linphone_core_defer_call_update(LinphoneCore *lc, LinphoneCall *call){ return -1; } -int linphone_core_start_accept_call_update(LinphoneCore *lc, LinphoneCall *call){ +int linphone_core_start_accept_call_update(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState next_state, const char *state_info){ SalMediaDescription *md; if (call->ice_session != NULL) { if (ice_session_nb_losing_pairs(call->ice_session) > 0) { @@ -3299,8 +3007,7 @@ int linphone_core_start_accept_call_update(LinphoneCore *lc, LinphoneCall *call) linphone_core_update_streams (lc,call,md); linphone_call_fix_call_parameters(call); } - if (call->state != LinphoneCallOutgoingEarlyMedia) /*don't change the state in case of outgoing early (SIP UPDATE)*/ - linphone_call_set_state(call,LinphoneCallStreamsRunning,"Connected (streams running)"); + linphone_call_set_state(call,next_state,state_info); return 0; } @@ -3329,14 +3036,14 @@ int linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const linphone_call_state_to_string(call->state)); return -1; } - return _linphone_core_accept_call_update(lc, call, params); + return _linphone_core_accept_call_update(lc, call, params, call->prevstate, linphone_call_state_to_string(call->prevstate)); } -int _linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params){ +int _linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params, LinphoneCallState next_state, const char *state_info){ SalMediaDescription *remote_desc; bool_t keep_sdp_version; #if defined(VIDEO_ENABLED) && defined(BUILD_UPNP) - bool_t old_has_video = call->params.has_video; + bool_t old_has_video = call->params->has_video; #endif remote_desc = sal_call_get_remote_media_description(call->op); @@ -3345,23 +3052,23 @@ int _linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, cons /* Remote has sent an INVITE with the same SDP as before, so send a 200 OK with the same SDP as before. */ ms_warning("SDP version has not changed, send same SDP as before."); sal_call_accept(call->op); - linphone_call_set_state(call,LinphoneCallStreamsRunning,"Connected (streams running)"); + linphone_call_set_state(call,next_state,state_info); return 0; } if (params==NULL){ - call->params.has_video=lc->video_policy.automatically_accept || call->current_params.has_video; + call->params->has_video=lc->video_policy.automatically_accept || call->current_params->has_video; }else - _linphone_call_params_copy(&call->params,params); + linphone_call_set_new_params(call,params); - if (call->params.has_video && !linphone_core_video_enabled(lc)){ + if (call->params->has_video && !linphone_core_video_enabled(lc)){ ms_warning("linphone_core_accept_call_update(): requested video but video support is globally disabled. Refusing video."); - call->params.has_video=FALSE; + call->params->has_video=FALSE; } - if (call->current_params.in_conference) { + if (call->current_params->in_conference) { ms_warning("Video isn't supported in conference"); - call->params.has_video = FALSE; + call->params->has_video = FALSE; } - call->params.has_video &= linphone_core_media_description_contains_video_stream(remote_desc); + call->params->has_video &= linphone_core_media_description_contains_video_stream(remote_desc); linphone_call_init_media_streams(call); /*so that video stream is initialized if necessary*/ if (call->ice_session != NULL) { if (linphone_call_prepare_ice(call,TRUE)==1) @@ -3372,7 +3079,7 @@ int _linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, cons if(call->upnp_session != NULL) { linphone_core_update_upnp_from_remote_media_description(call, sal_call_get_remote_media_description(call->op)); #ifdef VIDEO_ENABLED - if ((call->params.has_video) && (call->params.has_video != old_has_video)) { + if ((call->params->has_video) && (call->params->has_video != old_has_video)) { video_stream_prepare_video(call->videostream); if (linphone_core_update_upnp(lc, call)<0) { /* uPnP update failed, proceed with the call anyway. */ @@ -3383,7 +3090,7 @@ int _linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, cons } #endif //BUILD_UPNP - linphone_core_start_accept_call_update(lc, call); + linphone_core_start_accept_call_update(lc, call, next_state, state_info); return 0; } @@ -3466,7 +3173,7 @@ int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call, linphone_call_set_contact_op(call); if (params){ const SalMediaDescription *md = sal_call_get_remote_media_description(call->op); - _linphone_call_params_copy(&call->params,params); + linphone_call_set_new_params(call,params); // There might not be a md if the INVITE was lacking an SDP // In this case we use the parameters as is. if (md) { @@ -3493,8 +3200,7 @@ int linphone_core_accept_call_with_params(LinphoneCore *lc, LinphoneCall *call, linphone_call_update_remote_session_id_and_ver(call); sal_call_accept(call->op); - if (lc->vtable.display_status!=NULL) - lc->vtable.display_status(lc,_("Connected.")); + linphone_core_notify_display_status(lc,_("Connected.")); lc->current_call=call; linphone_call_set_state(call,LinphoneCallConnected,"Connected"); new_md=sal_call_get_final_media_description(call->op); @@ -3519,8 +3225,7 @@ int linphone_core_abort_call(LinphoneCore *lc, LinphoneCall *call, const char *e linphone_call_delete_upnp_session(call); #endif //BUILD_UPNP - if (lc->vtable.display_status!=NULL) - lc->vtable.display_status(lc,_("Call aborted") ); + linphone_core_notify_display_status(lc,_("Call aborted") ); linphone_call_set_state(call,LinphoneCallError,error); return 0; } @@ -3539,8 +3244,7 @@ static void terminate_call(LinphoneCore *lc, LinphoneCall *call){ linphone_call_delete_upnp_session(call); #endif //BUILD_UPNP - if (lc->vtable.display_status!=NULL) - lc->vtable.display_status(lc,_("Call ended") ); + linphone_core_notify_display_status(lc,_("Call ended") ); linphone_call_set_state(call,LinphoneCallEnd,"Call terminated"); } @@ -3640,6 +3344,8 @@ int linphone_core_terminate_all_calls(LinphoneCore *lc){ /** * Returns the current list of calls. + * @param[in] lc The LinphoneCore object + * @return \mslist{LinphoneCall} * * Note that this list is read-only and might be changed by the core after a function call to linphone_core_iterate(). * Similarly the LinphoneCall objects inside it might be destroyed without prior notice. @@ -3708,14 +3414,12 @@ int _linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call) return -1; } sal_call_set_local_media_description(call->op,call->localdesc); - if (sal_call_update(call->op,subject) != 0){ - if (lc->vtable.display_warning) - lc->vtable.display_warning(lc,_("Could not pause the call")); + if (sal_call_update(call->op,subject,FALSE) != 0){ + linphone_core_notify_display_warning(lc,_("Could not pause the call")); } lc->current_call=NULL; linphone_call_set_state(call,LinphoneCallPausing,"Pausing call"); - if (lc->vtable.display_status) - lc->vtable.display_status(lc,_("Pausing the current call...")); + linphone_core_notify_display_status(lc,_("Pausing the current call...")); if (call->audiostream || call->videostream) linphone_call_stop_media_streams (call); call->paused_by_app=FALSE; @@ -3769,7 +3473,7 @@ int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *call){ ms_warning("we cannot resume a call that has not been established and paused before"); return -1; } - if (call->params.in_conference==FALSE){ + if (call->params->in_conference==FALSE){ if (linphone_core_sound_resources_locked(lc)){ ms_warning("Cannot resume call %p because another call is locking the sound resources.",call); return -1; @@ -3792,16 +3496,15 @@ int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *call){ #endif //BUILD_UPNP sal_call_set_local_media_description(call->op,call->localdesc); sal_media_description_set_dir(call->localdesc,SalStreamSendRecv); - if (call->params.in_conference && !call->current_params.in_conference) subject="Conference"; - if(sal_call_update(call->op,subject) != 0){ + if (call->params->in_conference && !call->current_params->in_conference) subject="Conference"; + if ( sal_call_update(call->op,subject,FALSE) != 0){ return -1; } linphone_call_set_state(call,LinphoneCallResuming,"Resuming"); - if (call->params.in_conference==FALSE) + if (call->params->in_conference==FALSE) lc->current_call=call; snprintf(temp,sizeof(temp)-1,"Resuming the call with %s",linphone_call_get_remote_address_as_string(call)); - if (lc->vtable.display_status) - lc->vtable.display_status(lc,temp); + linphone_core_notify_display_status(lc,temp); return 0; } @@ -3821,6 +3524,7 @@ static int remote_address_compare(LinphoneCall *call, const LinphoneAddress *rad LinphoneCall *linphone_core_get_call_by_remote_address(LinphoneCore *lc, const char *remote_address){ LinphoneAddress *raddr=linphone_address_new(remote_address); MSList *elem=ms_list_find_custom(lc->calls,(int (*)(const void*,const void *))remote_address_compare,raddr); + linphone_address_unref(raddr); if (elem) return (LinphoneCall*) elem->data; return NULL; } @@ -4475,7 +4179,7 @@ void linphone_core_set_ringback(LinphoneCore *lc, const char *path){ if (lc->sound_conf.remote_ring!=0){ ms_free(lc->sound_conf.remote_ring); } - lc->sound_conf.remote_ring=ms_strdup(path); + lc->sound_conf.remote_ring=path?ms_strdup(path):NULL; } /** @@ -4763,9 +4467,23 @@ void linphone_core_set_firewall_policy(LinphoneCore *lc, LinphoneFirewallPolicy lp_config_set_string(lc->config,"net","firewall_policy",policy); } -LinphoneFirewallPolicy linphone_core_get_firewall_policy(const LinphoneCore *lc){ - const char *policy = lp_config_get_string(lc->config, "net", "firewall_policy", NULL); +inline LinphoneFirewallPolicy linphone_core_get_firewall_policy(const LinphoneCore *lc) { + return _linphone_core_get_firewall_policy_with_lie(lc, FALSE); +} +inline LinphoneFirewallPolicy _linphone_core_get_firewall_policy(const LinphoneCore *lc) { + return _linphone_core_get_firewall_policy_with_lie(lc, TRUE); +} + +LinphoneFirewallPolicy _linphone_core_get_firewall_policy_with_lie(const LinphoneCore *lc, bool_t lie){ + const char *policy; + if(lie) { + LinphoneTunnel *tunnel = linphone_core_get_tunnel(lc); + if(tunnel != NULL && linphone_tunnel_get_mode(tunnel)) { + return LinphonePolicyNoFirewall; + } + } + policy = lp_config_get_string(lc->config, "net", "firewall_policy", NULL); if ((policy == NULL) || (strcmp(policy, "0") == 0)) return LinphonePolicyNoFirewall; else if ((strcmp(policy, "nat_address") == 0) || (strcmp(policy, "1") == 0)) @@ -4780,23 +4498,19 @@ LinphoneFirewallPolicy linphone_core_get_firewall_policy(const LinphoneCore *lc) return LinphonePolicyNoFirewall; } -/** - * Get the list of call logs (past calls). - * - * @ingroup call_logs -**/ + + +/******************************************************************************* + * Call log related functions * + ******************************************************************************/ + const MSList * linphone_core_get_call_logs(LinphoneCore *lc){ return lc->call_logs; } -/** - * Erase the call log. - * - * @ingroup call_logs -**/ void linphone_core_clear_call_logs(LinphoneCore *lc){ lc->missed_calls=0; - ms_list_for_each(lc->call_logs,(void (*)(void*))linphone_call_log_destroy); + ms_list_for_each(lc->call_logs,(void (*)(void*))linphone_call_log_unref); lc->call_logs=ms_list_free(lc->call_logs); call_logs_write_to_config_file(lc); } @@ -4812,9 +4526,12 @@ void linphone_core_reset_missed_calls_count(LinphoneCore *lc) { void linphone_core_remove_call_log(LinphoneCore *lc, LinphoneCallLog *cl){ lc->call_logs = ms_list_remove(lc->call_logs, cl); call_logs_write_to_config_file(lc); - linphone_call_log_destroy(cl); + linphone_call_log_unref(cl); } + + + static void toggle_video_preview(LinphoneCore *lc, bool_t val){ #ifdef VIDEO_ENABLED if (val){ @@ -4889,6 +4606,18 @@ void linphone_core_enable_video_display(LinphoneCore *lc, bool_t enable) { reapply_network_bandwidth_settings(lc); } +void linphone_core_enable_video_source_reuse(LinphoneCore* lc, bool_t enable){ +#ifndef VIDEO_ENABLED + if (enable == TRUE) { + ms_warning("Cannot enable video display, this version of linphone was built without video support."); + } +#endif + lc->video_conf.reuse_preview_source = enable; + if( linphone_core_ready(lc) ){ + lp_config_set_int(lc->config, "video", "reuse_source", lc->video_conf.reuse_preview_source); + } +} + bool_t linphone_core_video_capture_enabled(LinphoneCore *lc) { return lc->video_conf.capture; } @@ -5357,11 +5086,13 @@ static void update_preview_size(LinphoneCore *lc, MSVideoSize oldvsize, MSVideoS void linphone_core_set_preferred_video_size(LinphoneCore *lc, MSVideoSize vsize){ if (video_size_supported(vsize)){ MSVideoSize oldvsize=lc->video_conf.preview_vsize; + if (oldvsize.width==0){ oldvsize=lc->video_conf.vsize; - update_preview_size(lc,oldvsize,vsize); } lc->video_conf.vsize=vsize; + update_preview_size(lc,oldvsize,vsize); + if (linphone_core_ready(lc)) lp_config_set_string(lc->config,"video","size",video_size_get_name(vsize)); } @@ -5447,6 +5178,7 @@ void linphone_core_set_preferred_framerate(LinphoneCore *lc, float fps){ } /** * Returns the preferred video framerate, previously set by linphone_core_set_preferred_framerate(). + * @ingroup media_parameters * @param lc the linphone core * @return frame rate in number of frames per seconds. **/ @@ -5457,16 +5189,22 @@ float linphone_core_get_preferred_framerate(LinphoneCore *lc){ /** * Ask the core to stream audio from and to files, instead of using the soundcard. + * @ingroup media_parameters + * @param[in] lc LinphoneCore object + * @param[in] yesno A boolean value asking to stream audio from and to files or not. **/ -void linphone_core_use_files(LinphoneCore *lc, bool_t yesno){ +void linphone_core_set_use_files(LinphoneCore *lc, bool_t yesno){ lc->use_files=yesno; } /** * Sets a wav file to be played when putting somebody on hold, - * or when files are used instead of soundcards (see linphone_core_use_files()). + * or when files are used instead of soundcards (see linphone_core_set_use_files()). * * The file must be a 16 bit linear wav file. + * @ingroup media_parameters + * @param[in] lc LinphoneCore object + * @param[in] file The path to the file to be played when putting somebody on hold. **/ void linphone_core_set_play_file(LinphoneCore *lc, const char *file){ LinphoneCall *call=linphone_core_get_current_call(lc); @@ -5484,10 +5222,13 @@ void linphone_core_set_play_file(LinphoneCore *lc, const char *file){ /** * Sets a wav file where incoming stream is to be recorded, - * when files are used instead of soundcards (see linphone_core_use_files()). + * when files are used instead of soundcards (see linphone_core_set_use_files()). * * This feature is different from call recording (linphone_call_params_set_record_file()) * The file will be a 16 bit linear wav file. + * @ingroup media_parameters + * @param[in] lc LinphoneCore object + * @param[in] file The path to the file where incoming stream is to be recorded. **/ void linphone_core_set_record_file(LinphoneCore *lc, const char *file){ LinphoneCall *call=linphone_core_get_current_call(lc); @@ -5659,7 +5400,7 @@ void linphone_core_stop_dtmf(LinphoneCore *lc){ * * @ingroup initializing **/ -void *linphone_core_get_user_data(LinphoneCore *lc){ +void *linphone_core_get_user_data(const LinphoneCore *lc){ return lc->data; } @@ -5805,15 +5546,11 @@ void sip_config_uninit(LinphoneCore *lc) } if (i>=20) ms_warning("Cannot complete unregistration, giving up"); } - ms_list_for_each(config->proxies,(void (*)(void*)) linphone_proxy_config_destroy); - ms_list_free(config->proxies); - config->proxies=NULL; + config->proxies=ms_list_free_with_data(config->proxies,(void (*)(void*)) _linphone_proxy_config_release); /*no longuer need to write proxy config if not changedlinphone_proxy_config_write_to_config_file(lc->config,NULL,i);*/ /*mark the end */ - ms_list_for_each(lc->auth_info,(void (*)(void*))linphone_auth_info_destroy); - ms_list_free(lc->auth_info); - lc->auth_info=NULL; + lc->auth_info=ms_list_free_with_data(lc->auth_info,(void (*)(void*))linphone_auth_info_destroy); /*now that we are unregisted, we no longer need the tunnel.*/ #ifdef TUNNEL_ENABLED @@ -6006,20 +5743,14 @@ static void linphone_core_uninit(LinphoneCore *lc) } #endif //BUILD_UPNP - if (lc->chatrooms){ - MSList *cr=ms_list_copy(lc->chatrooms); - MSList *elem; - for(elem=cr;elem!=NULL;elem=elem->next){ - linphone_chat_room_destroy((LinphoneChatRoom*)elem->data); - } - ms_list_free(cr); - } + ms_list_for_each(lc->chatrooms, (MSIterateFunc)linphone_chat_room_release); + lc->chatrooms = ms_list_free(lc->chatrooms); if (lp_config_needs_commit(lc->config)) lp_config_sync(lc->config); lp_config_destroy(lc->config); lc->config = NULL; /* Mark the config as NULL to block further calls */ - ms_list_for_each(lc->call_logs,(void (*)(void*))linphone_call_log_destroy); + ms_list_for_each(lc->call_logs,(void (*)(void*))linphone_call_log_unref); lc->call_logs=ms_list_free(lc->call_logs); ms_list_for_each(lc->last_recv_msg_ids,ms_free); @@ -6045,6 +5776,10 @@ static void linphone_core_uninit(LinphoneCore *lc) linphone_core_message_storage_close(lc); ms_exit(); linphone_core_set_state(lc,LinphoneGlobalOff,"Off"); + if (liblinphone_serialize_logs == TRUE) { + ortp_set_log_thread_id(0); + } + ms_list_free_with_data(lc->vtables,(void (*)(void *))linphone_vtable_destroy); } static void set_network_reachable(LinphoneCore* lc,bool_t isReachable, time_t curtime){ @@ -6052,7 +5787,7 @@ static void set_network_reachable(LinphoneCore* lc,bool_t isReachable, time_t cu const MSList *elem=linphone_core_get_proxy_config_list(lc); if (lc->network_reachable==isReachable) return; // no change, ignore. - + lc->network_reachable_to_be_notified=TRUE; ms_message("Network state is now [%s]",isReachable?"UP":"DOWN"); for(;elem!=NULL;elem=elem->next){ LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)elem->data; @@ -6223,8 +5958,8 @@ static PayloadType* find_payload_type_from_list(const char* type, int rate, int } -PayloadType* linphone_core_find_payload_type(LinphoneCore* lc, const char* type, int rate, int channels) { - PayloadType* result = find_payload_type_from_list(type, rate, channels, linphone_core_get_audio_codecs(lc)); +LinphonePayloadType* linphone_core_find_payload_type(LinphoneCore* lc, const char* type, int rate, int channels) { + LinphonePayloadType* result = find_payload_type_from_list(type, rate, channels, linphone_core_get_audio_codecs(lc)); if (result) { return result; } else { @@ -6262,11 +5997,24 @@ LinphoneGlobalState linphone_core_get_global_state(const LinphoneCore *lc){ } LinphoneCallParams *linphone_core_create_default_call_parameters(LinphoneCore *lc){ - LinphoneCallParams *p=ms_new0(LinphoneCallParams,1); + LinphoneCallParams *p=linphone_call_params_new(); linphone_core_init_default_params(lc, p); return p; } +/** + * Create a LinphoneCallParams suitable for linphone_core_invite_with_params(), linphone_core_accept_call_with_params(), linphone_core_accept_early_media_with_params(), + * linphone_core_accept_call_update(). + * The parameters are initialized according to the current LinphoneCore configuration and the current state of the LinphoneCall. + * @param lc the LinphoneCore + * @param call the call for which the parameters are to be build, or NULL in the case where the parameters are to be used for a new outgoing call. + * @return a new LinphoneCallParams + */ +LinphoneCallParams *linphone_core_create_call_params(LinphoneCore *lc, LinphoneCall *call){ + if (!call) return linphone_core_create_default_call_parameters(lc); + return linphone_call_params_copy(call->params); +} + const char *linphone_reason_to_string(LinphoneReason err){ switch(err){ case LinphoneReasonNone: @@ -6677,3 +6425,208 @@ bool_t linphone_core_sdp_200_ack_enabled(const LinphoneCore *lc) { void linphone_core_set_file_transfer_server(LinphoneCore *core, const char * server_url) { core->file_transfer_server=ms_strdup(server_url); } + +const char * linphone_core_get_file_transfer_server(LinphoneCore *core) { + return core->file_transfer_server; +} + +/** + * This function controls signaling features supported by the core. + * They are typically included in a SIP Supported header. + * @param lc the LinphoneCore + * @param tag the feature tag name + * @ingroup initializing +**/ +void linphone_core_add_supported_tag(LinphoneCore *lc, const char *tag){ + sal_add_supported_tag(lc->sal,tag); + lp_config_set_string(lc->config,"sip","supported",sal_get_supported_tags(lc->sal)); +} + +/** + * Remove a supported tag. @see linphone_core_add_supported_tag() + * @param lc the LinphoneCore + * @param tag the tag to remove + * @ingroup initializing +**/ +void linphone_core_remove_supported_tag(LinphoneCore *lc, const char *tag){ + sal_remove_supported_tag(lc->sal,tag); + lp_config_set_string(lc->config,"sip","supported",sal_get_supported_tags(lc->sal)); +} + +/** + * Enable RTCP feedback (also known as RTP/AVPF profile). + * Setting LinphoneAVPFDefault is equivalent to LinphoneAVPFDisabled. + * This setting can be overriden per LinphoneProxyConfig with linphone_proxy_config_set_avpf_mode(). + * The value set here is used for calls placed or received out of any proxy configured, or if the proxy config is configured with LinphoneAVPFDefault. + * @param lc the LinphoneCore + * @param mode the mode. +**/ +void linphone_core_set_avpf_mode(LinphoneCore *lc, LinphoneAVPFMode mode){ + if (mode==LinphoneAVPFDefault) mode=LinphoneAVPFDisabled; + lc->rtp_conf.avpf_mode=mode; + if (linphone_core_ready(lc)) lp_config_set_int(lc->config,"rtp","avpf",mode); +} + +/** + * Return AVPF enablement. See linphone_core_set_avpf_mode() . + * @param lc the core + * @return the avpf enablement mode. +**/ +LinphoneAVPFMode linphone_core_get_avpf_mode(const LinphoneCore *lc){ + return lc->rtp_conf.avpf_mode; +} + +/** + * Return the avpf report interval in seconds. + * @param lc the LinphoneCore + * @return the avpf report interval in seconds. +**/ +int linphone_core_get_avpf_rr_interval(const LinphoneCore *lc){ + return lp_config_get_int(lc->config,"rtp","avpf_rr_interval",5); +} + +/** + * Set the avpf report interval in seconds. + * This value can be overriden by the proxy config using linphone_proxy_config_set_avpf_rr_interval(). + * @param lc the core + * @param interval interval in seconds. +**/ +void linphone_core_set_avpf_rr_interval(LinphoneCore *lc, int interval){ + return lp_config_set_int(lc->config,"rtp","avpf_rr_interval",interval); +} + +int linphone_payload_type_get_type(const LinphonePayloadType *pt) { + return pt->type; +} + +int linphone_payload_type_get_normal_bitrate(const LinphonePayloadType *pt) { + return pt->normal_bitrate; +} + +char * linphone_payload_type_get_mime_type(const LinphonePayloadType *pt) { + return pt->mime_type; +} + +int linphone_payload_type_get_channels(const LinphonePayloadType *pt) { + return pt->channels; +} + +LinphoneCoreVTable *linphone_vtable_new() { + return ms_new0(LinphoneCoreVTable,1); +} + +void linphone_vtable_destroy(LinphoneCoreVTable* table) { + ms_free(table); +} +#define NOTIFY_IF_EXIST(function_name) \ + MSList* iterator; \ + ms_message ("Linphone core [%p] notifying [%s]",lc,#function_name);\ + for (iterator=lc->vtables; iterator!=NULL; iterator=iterator->next) \ + if (((LinphoneCoreVTable*)(iterator->data))->function_name)\ + ((LinphoneCoreVTable*)(iterator->data))->function_name + +void linphone_core_notify_global_state_changed(LinphoneCore *lc, LinphoneGlobalState gstate, const char *message) { + NOTIFY_IF_EXIST(global_state_changed)(lc,gstate,message); +} +void linphone_core_notify_call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *message){ + NOTIFY_IF_EXIST(call_state_changed)(lc,call,cstate,message); +} +void linphone_core_notify_call_encryption_changed(LinphoneCore *lc, LinphoneCall *call, bool_t on, const char *authentication_token) { + NOTIFY_IF_EXIST(call_encryption_changed)(lc,call,on,authentication_token); +} +void linphone_core_notify_registration_state_changed(LinphoneCore *lc, LinphoneProxyConfig *cfg, LinphoneRegistrationState cstate, const char *message){ + NOTIFY_IF_EXIST(registration_state_changed)(lc,cfg,cstate,message); +} +void linphone_core_notify_show_interface(LinphoneCore *lc){ + NOTIFY_IF_EXIST(show)(lc); +} +void linphone_core_notify_display_status(LinphoneCore *lc, const char *message) { + NOTIFY_IF_EXIST(display_status)(lc,message); +} +void linphone_core_notify_display_message(LinphoneCore *lc, const char *message){ + NOTIFY_IF_EXIST(display_message)(lc,message); +} +void linphone_core_notify_display_warning(LinphoneCore *lc, const char *message){ + NOTIFY_IF_EXIST(display_warning)(lc,message); +} +void linphone_core_notify_display_url(LinphoneCore *lc, const char *message, const char *url){ + NOTIFY_IF_EXIST(display_url)(lc,message,url); +} +void linphone_core_notify_notify_presence_received(LinphoneCore *lc, LinphoneFriend * lf){ + NOTIFY_IF_EXIST(notify_presence_received)(lc,lf); +} +void linphone_core_notify_new_subscription_requested(LinphoneCore *lc, LinphoneFriend *lf, const char *url){ + NOTIFY_IF_EXIST(new_subscription_requested)(lc,lf,url); +} +void linphone_core_notify_auth_info_requested(LinphoneCore *lc, const char *realm, const char *username, const char *domain){ + NOTIFY_IF_EXIST(auth_info_requested)(lc,realm,username,domain); +} +void linphone_core_notify_call_log_updated(LinphoneCore *lc, LinphoneCallLog *newcl){ + NOTIFY_IF_EXIST(call_log_updated)(lc,newcl); +} +void linphone_core_notify_text_message_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddress *from, const char *message){ + NOTIFY_IF_EXIST(text_received)(lc,room,from,message); +} +void linphone_core_notify_message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *message){ + NOTIFY_IF_EXIST(message_received)(lc,room,message); +} +void linphone_core_notify_file_transfer_recv(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, const char* buff, size_t size) { + NOTIFY_IF_EXIST(file_transfer_recv)(lc,message,content,buff,size); +} +void linphone_core_notify_file_transfer_send(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, char* buff, size_t* size) { + NOTIFY_IF_EXIST(file_transfer_send)(lc,message,content,buff,size); +} +void linphone_core_notify_file_transfer_progress_indication(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, size_t progress) { + NOTIFY_IF_EXIST(file_transfer_progress_indication)(lc,message,content,progress); +} +void linphone_core_notify_is_composing_received(LinphoneCore *lc, LinphoneChatRoom *room) { + NOTIFY_IF_EXIST(is_composing_received)(lc,room); +} +void linphone_core_notify_dtmf_received(LinphoneCore* lc, LinphoneCall *call, int dtmf) { + NOTIFY_IF_EXIST(dtmf_received)(lc,call,dtmf); +} +bool_t linphone_core_dtmf_received_has_listener(const LinphoneCore* lc) { + MSList* iterator; + for (iterator=lc->vtables; iterator!=NULL; iterator=iterator->next) + if (((LinphoneCoreVTable*)(iterator->data))->dtmf_received) + return TRUE; + return FALSE; +} +void linphone_core_notify_refer_received(LinphoneCore *lc, const char *refer_to) { + NOTIFY_IF_EXIST(refer_received)(lc,refer_to); +} +void linphone_core_notify_buddy_info_updated(LinphoneCore *lc, LinphoneFriend *lf) { + NOTIFY_IF_EXIST(buddy_info_updated)(lc,lf); +} +void linphone_core_notify_transfer_state_changed(LinphoneCore *lc, LinphoneCall *transfered, LinphoneCallState new_call_state) { + NOTIFY_IF_EXIST(transfer_state_changed)(lc,transfered,new_call_state); +} +void linphone_core_notify_call_stats_updated(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallStats *stats) { + NOTIFY_IF_EXIST(call_stats_updated)(lc,call,stats); +} +void linphone_core_notify_info_received(LinphoneCore *lc, LinphoneCall *call, const LinphoneInfoMessage *msg) { + NOTIFY_IF_EXIST(info_received)(lc,call,msg); +} +void linphone_core_notify_configuring_status(LinphoneCore *lc, LinphoneConfiguringState status, const char *message) { + NOTIFY_IF_EXIST(configuring_status)(lc,status,message); +} +void linphone_core_notify_network_reachable(LinphoneCore *lc, bool_t reachable) { + NOTIFY_IF_EXIST(network_reachable)(lc,reachable); +} +void linphone_core_notify_notify_received(LinphoneCore *lc, LinphoneEvent *lev, const char *notified_event, const LinphoneContent *body) { + NOTIFY_IF_EXIST(notify_received)(lc,lev,notified_event,body); +} +void linphone_core_notify_subscription_state_changed(LinphoneCore *lc, LinphoneEvent *lev, LinphoneSubscriptionState state) { + NOTIFY_IF_EXIST(subscription_state_changed)(lc,lev,state); +} +void linphone_core_notify_publish_state_changed(LinphoneCore *lc, LinphoneEvent *lev, LinphonePublishState state) { + NOTIFY_IF_EXIST(publish_state_changed)(lc,lev,state); +} +void linphone_core_add_listener(LinphoneCore *lc, LinphoneCoreVTable *vtable) { + ms_message("Vtable [%p] registered on core [%p]",lc,vtable); + lc->vtables=ms_list_append(lc->vtables,vtable); +} +void linphone_core_remove_listener(LinphoneCore *lc, const LinphoneCoreVTable *vtable) { + ms_message("Vtable [%p] unregistered on core [%p]",lc,vtable); + lc->vtables=ms_list_remove(lc->vtables,(void*)vtable); +} diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index 157c15073..9ded4edaa 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -24,6 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "mediastreamer2/mscommon.h" #include "mediastreamer2/msvideo.h" #include "mediastreamer2/mediastream.h" +#include "mediastreamer2/bitratecontrol.h" #ifdef IN_LINPHONE #include "sipsetup.h" @@ -249,86 +250,61 @@ LinphoneDictionary* lp_config_section_to_dict( const LpConfig* lpconfig, const c void lp_config_load_dict_to_section( LpConfig* lpconfig, const char* section, const LinphoneDictionary* dict); -#ifdef IN_LINPHONE -#include "linphonefriend.h" -#include "event.h" -#else -#include "linphone/linphonefriend.h" -#include "linphone/event.h" -#endif - -LINPHONE_PUBLIC LinphoneAddress * linphone_address_new(const char *addr); -LINPHONE_PUBLIC LinphoneAddress * linphone_address_clone(const LinphoneAddress *addr); -LINPHONE_PUBLIC LinphoneAddress * linphone_address_ref(LinphoneAddress *addr); -LINPHONE_PUBLIC void linphone_address_unref(LinphoneAddress *addr); -LINPHONE_PUBLIC const char *linphone_address_get_scheme(const LinphoneAddress *u); -LINPHONE_PUBLIC const char *linphone_address_get_display_name(const LinphoneAddress* u); -LINPHONE_PUBLIC const char *linphone_address_get_username(const LinphoneAddress *u); -LINPHONE_PUBLIC const char *linphone_address_get_domain(const LinphoneAddress *u); -LINPHONE_PUBLIC int linphone_address_get_port(const LinphoneAddress *u); -LINPHONE_PUBLIC void linphone_address_set_display_name(LinphoneAddress *u, const char *display_name); -LINPHONE_PUBLIC void linphone_address_set_username(LinphoneAddress *uri, const char *username); -LINPHONE_PUBLIC void linphone_address_set_domain(LinphoneAddress *uri, const char *host); -LINPHONE_PUBLIC void linphone_address_set_port(LinphoneAddress *uri, int port); -/*remove tags, params etc... so that it is displayable to the user*/ -LINPHONE_PUBLIC void linphone_address_clean(LinphoneAddress *uri); -LINPHONE_PUBLIC bool_t linphone_address_is_secure(const LinphoneAddress *uri); -LINPHONE_PUBLIC LinphoneTransportType linphone_address_get_transport(const LinphoneAddress *uri); -LINPHONE_PUBLIC void linphone_address_set_transport(LinphoneAddress *uri,LinphoneTransportType type); -LINPHONE_PUBLIC char *linphone_address_as_string(const LinphoneAddress *u); -LINPHONE_PUBLIC char *linphone_address_as_string_uri_only(const LinphoneAddress *u); -LINPHONE_PUBLIC bool_t linphone_address_weak_equal(const LinphoneAddress *a1, const LinphoneAddress *a2); -LINPHONE_PUBLIC void linphone_address_destroy(LinphoneAddress *u); - /** - * Create a #LinphoneAddress object by parsing the user supplied address, given as a string. - * @param[in] lc #LinphoneCore object - * @param[in] address String containing the user supplied address - * @return The create #LinphoneAddress object - * @ingroup linphone_address - */ -LINPHONE_PUBLIC LinphoneAddress * linphone_core_create_address(LinphoneCore *lc, const char *address); - -struct _SipSetupContext; - - -/** - * Enum representing the direction of a call. - * @ingroup call_logs + * @addtogroup media_parameters + * @{ **/ -enum _LinphoneCallDir { - LinphoneCallOutgoing, /**< outgoing calls*/ - LinphoneCallIncoming /**< incoming calls*/ + +/** + * Object representing an RTP payload type. + */ +typedef PayloadType LinphonePayloadType; + +/** + * Get the type of payload. + * @param[in] pt LinphonePayloadType object + * @return The type of payload. + */ +LINPHONE_PUBLIC int linphone_payload_type_get_type(const LinphonePayloadType *pt); + +/** + * Get the normal bitrate in bits/s. + * @param[in] pt LinphonePayloadType object + * @return The normal bitrate in bits/s. + */ +LINPHONE_PUBLIC int linphone_payload_type_get_normal_bitrate(const LinphonePayloadType *pt); + +/** + * Get the mime type. + * @param[in] pt LinphonePayloadType object + * @return The mime type. + */ +LINPHONE_PUBLIC char * linphone_payload_type_get_mime_type(const LinphonePayloadType *pt); + +/** + * Get the number of channels. + * @param[in] pt LinphonePayloadType object + * @return The number of channels. + */ +LINPHONE_PUBLIC int linphone_payload_type_get_channels(const LinphonePayloadType *pt); + + +/** + * Enum describing RTP AVPF activation modes. +**/ +enum _LinphoneAVPFMode{ + LinphoneAVPFDefault=-1, /** A text message has been received */ - LinphoneCoreFileTransferRecvCb file_transfer_received; /** Callback to store file received attached to a #LinphoneChatMessage */ + LinphoneCoreFileTransferRecvCb file_transfer_recv; /** Callback to store file received attached to a #LinphoneChatMessage */ LinphoneCoreFileTransferSendCb file_transfer_send; /** Callback to collect file chunk to be sent for a #LinphoneChatMessage */ LinphoneCoreFileTransferProgressIndicationCb file_transfer_progress_indication; /**Callback to indicate file transfer progress*/ + LinphoneCoreNetworkReachableCb network_reachable; /** Call back to report IP network status (I.E up/down)*/ } LinphoneCoreVTable; +/** + * Instantiate a vtable with all argument set to NULL + * @returns newly allocated vtable + */ +LINPHONE_PUBLIC LinphoneCoreVTable *linphone_vtable_new(); + +/** + * destroy a vtable. + * @param vtable to be destroyed + */ +LINPHONE_PUBLIC void linphone_vtable_destroy(LinphoneCoreVTable* table); + /** * @} **/ @@ -1660,6 +1764,14 @@ LINPHONE_PUBLIC void linphone_core_set_log_level(OrtpLogLevel loglevel); LINPHONE_PUBLIC void linphone_core_enable_logs(FILE *file); LINPHONE_PUBLIC void linphone_core_enable_logs_with_cb(OrtpLogFunc logfunc); LINPHONE_PUBLIC void linphone_core_disable_logs(void); + +/** + * Enable logs serialization (output logs from either the thread that creates the linphone core or the thread that calls linphone_core_iterate()). + * Must be called before creating the linphone core. + * @ingroup misc + */ +LINPHONE_PUBLIC void linphone_core_serialize_logs(void); + LINPHONE_PUBLIC const char *linphone_core_get_version(void); LINPHONE_PUBLIC const char *linphone_core_get_user_agent(LinphoneCore *lc); /** @@ -1691,24 +1803,26 @@ LINPHONE_PUBLIC LinphoneCore *linphone_core_new_with_config(const LinphoneCoreVT /* function to be periodically called in a main loop */ /* For ICE to work properly it should be called every 20ms */ LINPHONE_PUBLIC void linphone_core_iterate(LinphoneCore *lc); -#if 0 /*not implemented yet*/ + /** * @ingroup initializing - * Provide Linphone Core with an unique identifier. This be later used to identified contact address coming from this device. - * Value is not saved. + * add a listener to be notified of linphone core events. Once events are received, registered vtable are invoked in order. + * @param vtable a LinphoneCoreVTable structure holding your application callbacks. Object is owned by linphone core until linphone_core_remove_listener. * @param lc object * @param string identifying the device, can be EMEI or UDID * */ -void linphone_core_set_device_identifier(LinphoneCore *lc,const char* device_id); +LINPHONE_PUBLIC void linphone_core_add_listener(LinphoneCore *lc, LinphoneCoreVTable *vtable); /** * @ingroup initializing - * get Linphone unique identifier + * remove a listener registred by linphone_core_add_listener. + * @param vtable a LinphoneCoreVTable structure holding your application callbacks + * @param lc object + * @param string identifying the device, can be EMEI or UDID * */ -const char* linphone_core_get_device_identifier(const LinphoneCore *lc); +LINPHONE_PUBLIC void linphone_core_remove_listener(LinphoneCore *lc, const LinphoneCoreVTable *vtable); -#endif /*sets the user-agent string in sip messages, ideally called just after linphone_core_new() or linphone_core_init() */ LINPHONE_PUBLIC void linphone_core_set_user_agent(LinphoneCore *lc, const char *ua_name, const char *version); @@ -1729,7 +1843,16 @@ LINPHONE_PUBLIC int linphone_core_transfer_call_to_another(LinphoneCore *lc, Lin LINPHONE_PUBLIC LinphoneCall * linphone_core_start_refered_call(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params); -LINPHONE_PUBLIC bool_t linphone_core_inc_invite_pending(LinphoneCore*lc); +/** @deprecated Use linphone_core_is_incoming_invite_pending() instead. */ +#define linphone_core_inc_invite_pending(lc) linphone_core_is_incoming_invite_pending(lc) + +/** + * Tells whether there is an incoming invite pending. + * @ingroup call_control + * @param[in] lc LinphoneCore object + * @return A boolean telling whether an incoming invite is pending or not. + */ +LINPHONE_PUBLIC bool_t linphone_core_is_incoming_invite_pending(LinphoneCore*lc); LINPHONE_PUBLIC bool_t linphone_core_in_call(const LinphoneCore *lc); @@ -1775,9 +1898,12 @@ LINPHONE_PUBLIC int linphone_core_accept_call_update(LinphoneCore *lc, LinphoneC * Get default call parameters reflecting current linphone core configuration * @param lc LinphoneCore object * @return LinphoneCallParams + * @deprecated use linphone_core_create_call_params() */ LINPHONE_PUBLIC LinphoneCallParams *linphone_core_create_default_call_parameters(LinphoneCore *lc); +LINPHONE_PUBLIC LinphoneCallParams *linphone_core_create_call_params(LinphoneCore *lc, LinphoneCall *call); + LINPHONE_PUBLIC LinphoneCall *linphone_core_get_call_by_remote_address(LinphoneCore *lc, const char *remote_address); LINPHONE_PUBLIC void linphone_core_send_dtmf(LinphoneCore *lc,char dtmf); @@ -1808,6 +1934,9 @@ LINPHONE_PUBLIC int linphone_core_get_upload_bandwidth(const LinphoneCore *lc); LINPHONE_PUBLIC void linphone_core_enable_adaptive_rate_control(LinphoneCore *lc, bool_t enabled); LINPHONE_PUBLIC bool_t linphone_core_adaptive_rate_control_enabled(const LinphoneCore *lc); +LINPHONE_PUBLIC void linphone_core_set_adaptive_rate_algorithm(LinphoneCore *lc, const char *algorithm); +LINPHONE_PUBLIC const char* linphone_core_get_adaptive_rate_algorithm(const LinphoneCore *lc); + LINPHONE_PUBLIC void linphone_core_set_download_ptime(LinphoneCore *lc, int ptime); LINPHONE_PUBLIC int linphone_core_get_download_ptime(LinphoneCore *lc); @@ -1859,48 +1988,48 @@ LINPHONE_PUBLIC int linphone_core_set_video_codecs(LinphoneCore *lc, MSList *cod /** * Tells whether the specified payload type is enabled. * @param[in] lc #LinphoneCore object. - * @param[in] pt The #PayloadType we want to know is enabled or not. + * @param[in] pt The #LinphonePayloadType we want to know is enabled or not. * @returns TRUE if the payload type is enabled, FALSE if disabled. * @ingroup media_parameters */ -LINPHONE_PUBLIC bool_t linphone_core_payload_type_enabled(LinphoneCore *lc, const PayloadType *pt); +LINPHONE_PUBLIC bool_t linphone_core_payload_type_enabled(LinphoneCore *lc, const LinphonePayloadType *pt); /** * Tells whether the specified payload type represents a variable bitrate codec. * @param[in] lc #LinphoneCore object. - * @param[in] pt The #PayloadType we want to know + * @param[in] pt The #LinphonePayloadType we want to know * @returns TRUE if the payload type represents a VBR codec, FALSE if disabled. * @ingroup media_parameters */ -LINPHONE_PUBLIC bool_t linphone_core_payload_type_is_vbr(LinphoneCore *lc, const PayloadType *pt); +LINPHONE_PUBLIC bool_t linphone_core_payload_type_is_vbr(LinphoneCore *lc, const LinphonePayloadType *pt); /** * Set an explicit bitrate (IP bitrate, not codec bitrate) for a given codec, in kbit/s. * @param[in] lc the #LinphoneCore object - * @param[in] pt the #PayloadType to modify. + * @param[in] pt the #LinphonePayloadType to modify. * @param[in] bitrate the IP bitrate in kbit/s. * @ingroup media_parameters **/ -LINPHONE_PUBLIC void linphone_core_set_payload_type_bitrate(LinphoneCore *lc, PayloadType *pt, int bitrate); +LINPHONE_PUBLIC void linphone_core_set_payload_type_bitrate(LinphoneCore *lc, LinphonePayloadType *pt, int bitrate); /** * Get the bitrate explicitely set with linphone_core_set_payload_type_bitrate(). * @param[in] lc the #LinphoneCore object - * @param[in] pt the #PayloadType to modify. + * @param[in] pt the #LinphonePayloadType to modify. * @return bitrate the IP bitrate in kbit/s, or -1 if an error occured. * @ingroup media_parameters **/ -LINPHONE_PUBLIC int linphone_core_get_payload_type_bitrate(LinphoneCore *lc, const PayloadType *pt); +LINPHONE_PUBLIC int linphone_core_get_payload_type_bitrate(LinphoneCore *lc, const LinphonePayloadType *pt); /** * Enable or disable the use of the specified payload type. * @param[in] lc #LinphoneCore object. - * @param[in] pt The #PayloadType to enable or disable. It can be retrieved using #linphone_core_find_payload_type + * @param[in] pt The #LinphonePayloadType to enable or disable. It can be retrieved using #linphone_core_find_payload_type * @param[in] enable TRUE to enable the payload type, FALSE to disable it. * @return 0 if successful, any other value otherwise. * @ingroup media_parameters */ -LINPHONE_PUBLIC int linphone_core_enable_payload_type(LinphoneCore *lc, PayloadType *pt, bool_t enable); +LINPHONE_PUBLIC int linphone_core_enable_payload_type(LinphoneCore *lc, LinphonePayloadType *pt, bool_t enable); /** * Wildcard value used by #linphone_core_find_payload_type to ignore rate in search algorithm @@ -1922,7 +2051,7 @@ LINPHONE_PUBLIC int linphone_core_enable_payload_type(LinphoneCore *lc, PayloadT * @param channels number of channels, can be #LINPHONE_FIND_PAYLOAD_IGNORE_CHANNELS * @return Returns NULL if not found. */ -LINPHONE_PUBLIC PayloadType* linphone_core_find_payload_type(LinphoneCore* lc, const char* type, int rate, int channels) ; +LINPHONE_PUBLIC LinphonePayloadType* linphone_core_find_payload_type(LinphoneCore* lc, const char* type, int rate, int channels) ; LINPHONE_PUBLIC int linphone_core_get_payload_type_number(LinphoneCore *lc, const PayloadType *pt); @@ -1946,12 +2075,17 @@ LINPHONE_PUBLIC void linphone_core_remove_proxy_config(LinphoneCore *lc, Linphon LINPHONE_PUBLIC const MSList *linphone_core_get_proxy_config_list(const LinphoneCore *lc); -LINPHONE_PUBLIC void linphone_core_set_default_proxy(LinphoneCore *lc, LinphoneProxyConfig *config); +/** @deprecated Use linphone_core_set_default_proxy_config() instead. */ +#define linphone_core_set_default_proxy(lc, config) linphone_core_set_default_proxy_config(lc, config) void linphone_core_set_default_proxy_index(LinphoneCore *lc, int index); LINPHONE_PUBLIC int linphone_core_get_default_proxy(LinphoneCore *lc, LinphoneProxyConfig **config); +LINPHONE_PUBLIC LinphoneProxyConfig * linphone_core_get_default_proxy_config(LinphoneCore *lc); + +LINPHONE_PUBLIC void linphone_core_set_default_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *config); + /** * Create an authentication information with default values from Linphone core. * @param[in] lc #LinphoneCore object @@ -2260,34 +2394,54 @@ bool_t linphone_core_get_rtp_no_xmit_on_audio_mute(const LinphoneCore *lc); void linphone_core_set_rtp_no_xmit_on_audio_mute(LinphoneCore *lc, bool_t val); -/* returns a list of LinphoneCallLog */ -LINPHONE_PUBLIC const MSList * linphone_core_get_call_logs(LinphoneCore *lc); -LINPHONE_PUBLIC void linphone_core_clear_call_logs(LinphoneCore *lc); +/******************************************************************************* + * Call log related functions * + ******************************************************************************/ + +/** + * @addtogroup call_logs + * @{ +**/ + +/** + * Get the list of call logs (past calls). + * @param[in] lc LinphoneCore object + * @return \mslist{LinphoneCallLog} +**/ +LINPHONE_PUBLIC const MSList * linphone_core_get_call_logs(LinphoneCore *lc); + +/** + * Erase the call log. + * @param[in] lc LinphoneCore object +**/ +LINPHONE_PUBLIC void linphone_core_clear_call_logs(LinphoneCore *lc); /** * Get the number of missed calls. * Once checked, this counter can be reset with linphone_core_reset_missed_calls_count(). * @param[in] lc #LinphoneCore object. * @returns The number of missed calls. - * @ingroup call_logs **/ -LINPHONE_PUBLIC int linphone_core_get_missed_calls_count(LinphoneCore *lc); +LINPHONE_PUBLIC int linphone_core_get_missed_calls_count(LinphoneCore *lc); /** * Reset the counter of missed calls. * @param[in] lc #LinphoneCore object. - * @ingroup call_logs **/ -LINPHONE_PUBLIC void linphone_core_reset_missed_calls_count(LinphoneCore *lc); +LINPHONE_PUBLIC void linphone_core_reset_missed_calls_count(LinphoneCore *lc); /** * Remove a specific call log from call history list. * This function destroys the call log object. It must not be accessed anymore by the application after calling this function. * @param[in] lc #LinphoneCore object * @param[in] call_log #LinphoneCallLog object to remove. - * @ingroup call_logs **/ -LINPHONE_PUBLIC void linphone_core_remove_call_log(LinphoneCore *lc, LinphoneCallLog *call_log); +LINPHONE_PUBLIC void linphone_core_remove_call_log(LinphoneCore *lc, LinphoneCallLog *call_log); + +/** + * @} +**/ + /* video support */ LINPHONE_PUBLIC bool_t linphone_core_video_supported(LinphoneCore *lc); @@ -2336,6 +2490,24 @@ LINPHONE_PUBLIC void linphone_core_enable_video_capture(LinphoneCore *lc, bool_t **/ LINPHONE_PUBLIC void linphone_core_enable_video_display(LinphoneCore *lc, bool_t enable); + +/** + * Enable or disable video source reuse when switching from preview to actual video call. + * + * This source reuse is useful when you always display the preview, even before calls are initiated. + * By keeping the video source for the transition to a real video call, you will smooth out the + * source close/reopen cycle. + * + * This function does not have any effect durfing calls. It just indicates the #LinphoneCore to + * initiate future calls with video source reuse or not. + * Also, at the end of a video call, the source will be closed whatsoever for now. + * @param[in] lc #LinphoneCore object + * @param[in] enable TRUE to enable video source reuse. FALSE to disable it for subsequent calls. + * @ingroup media_parameters + * + */ +LINPHONE_PUBLIC void linphone_core_enable_video_source_reuse(LinphoneCore* lc, bool_t enable); + /** * Tells whether video capture is enabled. * @param[in] lc #LinphoneCore object. @@ -2456,8 +2628,10 @@ LINPHONE_PUBLIC int linphone_core_get_camera_sensor_rotation(LinphoneCore *lc); /* start or stop streaming video in case of embedded window */ void linphone_core_show_video(LinphoneCore *lc, bool_t show); +/** @deprecated Use linphone_core_set_use_files() instead. */ +#define linphone_core_use_files(lc, yesno) linphone_core_set_use_files(lc, yesno) /*play/record support: use files instead of soundcard*/ -LINPHONE_PUBLIC void linphone_core_use_files(LinphoneCore *lc, bool_t yesno); +LINPHONE_PUBLIC void linphone_core_set_use_files(LinphoneCore *lc, bool_t yesno); LINPHONE_PUBLIC void linphone_core_set_play_file(LinphoneCore *lc, const char *file); LINPHONE_PUBLIC void linphone_core_set_record_file(LinphoneCore *lc, const char *file); @@ -2494,7 +2668,7 @@ LINPHONE_PUBLIC void linphone_core_enable_keep_alive(LinphoneCore* lc,bool_t ena */ LINPHONE_PUBLIC bool_t linphone_core_keep_alive_enabled(LinphoneCore* lc); -LINPHONE_PUBLIC void *linphone_core_get_user_data(LinphoneCore *lc); +LINPHONE_PUBLIC void *linphone_core_get_user_data(const LinphoneCore *lc); LINPHONE_PUBLIC void linphone_core_set_user_data(LinphoneCore *lc, void *userdata); /* returns LpConfig object to read/write to the config file: usefull if you wish to extend @@ -2654,7 +2828,7 @@ typedef struct _LinphoneTunnel LinphoneTunnel; /** * get tunnel instance if available */ -LINPHONE_PUBLIC LinphoneTunnel *linphone_core_get_tunnel(LinphoneCore *lc); +LINPHONE_PUBLIC LinphoneTunnel *linphone_core_get_tunnel(const LinphoneCore *lc); LINPHONE_PUBLIC void linphone_core_set_sip_dscp(LinphoneCore *lc, int dscp); LINPHONE_PUBLIC int linphone_core_get_sip_dscp(const LinphoneCore *lc); @@ -2754,6 +2928,13 @@ LINPHONE_PUBLIC void linphone_core_set_tone(LinphoneCore *lc, LinphoneToneID id, * */ LINPHONE_PUBLIC void linphone_core_set_file_transfer_server(LinphoneCore *core, const char * server_url); +/** + * Get the globaly set http file transfer server to be used for content type application/vnd.gsma.rcs-ft-http+xml. + * @param[in] core #LinphoneCore from which to get the server_url + * @return URL of the file server like https://file.linphone.org/upload.php + * */ +LINPHONE_PUBLIC const char * linphone_core_get_file_transfer_server(LinphoneCore *core); + /** * Returns a null terminated table of strings containing the file format extension supported for call recording. * @param core the core @@ -2762,6 +2943,16 @@ LINPHONE_PUBLIC void linphone_core_set_file_transfer_server(LinphoneCore *core, **/ LINPHONE_PUBLIC const char ** linphone_core_get_supported_file_formats(LinphoneCore *core); +LINPHONE_PUBLIC void linphone_core_add_supported_tag(LinphoneCore *core, const char *tag); + +LINPHONE_PUBLIC void linphone_core_remove_supported_tag(LinphoneCore *core, const char *tag); + +LINPHONE_PUBLIC void linphone_core_set_avpf_mode(LinphoneCore *lc, LinphoneAVPFMode mode); + +LINPHONE_PUBLIC LinphoneAVPFMode linphone_core_get_avpf_mode(const LinphoneCore *lc); + +LINPHONE_PUBLIC int linphone_core_get_avpf_rr_interval(const LinphoneCore *lc); + #ifdef __cplusplus } #endif diff --git a/coreapi/linphonecore_jni.cc b/coreapi/linphonecore_jni.cc index c43b6e3c3..bcdf0fdf0 100644 --- a/coreapi/linphonecore_jni.cc +++ b/coreapi/linphonecore_jni.cc @@ -55,6 +55,7 @@ extern "C" void libmsbcg729_init(); #ifdef HAVE_WEBRTC extern "C" void libmswebrtc_init(); #endif +#include #endif /*ANDROID*/ @@ -76,25 +77,6 @@ extern "C" void libmswebrtc_init(); return jUserDataObj; \ } - -#define RETURN_PROXY_CONFIG_USER_DATA_OBJECT(javaclass, funcprefix, cobj) \ - { \ - jclass jUserDataObjectClass; \ - jmethodID jUserDataObjectCtor; \ - jobject jUserDataObj; \ - jUserDataObj = (jobject)funcprefix ## _get_user_data(cobj); \ - if (jUserDataObj == NULL) { \ - jUserDataObjectClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/" javaclass)); \ - jUserDataObjectCtor = env->GetMethodID(jUserDataObjectClass,"", "(J)V"); \ - jUserDataObj = env->NewObject(jUserDataObjectClass, jUserDataObjectCtor,(jlong) cobj); \ - jUserDataObj = env->NewGlobalRef(jUserDataObj); \ - funcprefix ## _set_user_data(cobj, jUserDataObj); \ - env->DeleteGlobalRef(jUserDataObjectClass); \ - } \ - return jUserDataObj; \ - } - - static JavaVM *jvm=0; static const char* LogDomain = "Linphone"; static jclass handler_class; @@ -208,6 +190,9 @@ public: vTable.notify_received=notifyReceived; vTable.publish_state_changed=publishStateChanged; vTable.configuring_status=configuringStatus; + vTable.file_transfer_progress_indication=fileTransferProgressIndication; + vTable.file_transfer_send=fileTransferSend; + vTable.file_transfer_recv=fileTransferRecv; listenerClass = (jclass)env->NewGlobalRef(env->GetObjectClass( alistener)); @@ -310,6 +295,10 @@ public: configuringStateId = env->GetMethodID(listenerClass,"configuringStatus","(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneCore$RemoteProvisioningState;Ljava/lang/String;)V"); configuringStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCore$RemoteProvisioningState")); configuringStateFromIntId = env->GetStaticMethodID(configuringStateClass,"fromInt","(I)Lorg/linphone/core/LinphoneCore$RemoteProvisioningState;"); + + fileTransferProgressIndicationId = env->GetMethodID(listenerClass, "fileTransferProgressIndication", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneContent;I)V"); + fileTransferSendId = env->GetMethodID(listenerClass, "fileTransferSend", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneContent;Ljava/nio/ByteBuffer;I)I"); + fileTransferRecvId = env->GetMethodID(listenerClass, "fileTransferRecv", "(Lorg/linphone/core/LinphoneCore;Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneContent;[BI)V"); } ~LinphoneCoreData() { @@ -417,6 +406,10 @@ public: jclass subscriptionDirClass; jmethodID subscriptionDirFromIntId; + jmethodID fileTransferProgressIndicationId; + jmethodID fileTransferSendId; + jmethodID fileTransferRecvId; + LinphoneCoreVTable vTable; static void showInterfaceCb(LinphoneCore *lc) { @@ -467,9 +460,35 @@ public: ,env->CallStaticObjectMethod(lcData->globalStateClass,lcData->globalStateFromIntId,(jint)gstate), message ? env->NewStringUTF(message) : NULL); } + /* + * returns the java LinphoneProxyConfig associated with a C LinphoneProxyConfig. + **/ + jobject getProxy(JNIEnv *env , LinphoneProxyConfig *proxy, jobject core){ + jobject jobj=0; + + if (proxy!=NULL){ + void *up=linphone_proxy_config_get_user_data(proxy); + + if (up==NULL){ + jobj=env->NewObject(proxyClass,proxyCtrId,core,(jlong)proxy); + linphone_proxy_config_set_user_data(proxy,(void*)env->NewWeakGlobalRef(jobj)); + linphone_proxy_config_ref(proxy); + }else{ + //promote the weak ref to local ref + jobj=env->NewLocalRef((jobject)up); + if (jobj == NULL){ + //the weak ref was dead + jobj=env->NewObject(proxyClass,proxyCtrId,core,(jlong)proxy); + linphone_proxy_config_set_user_data(proxy,(void*)env->NewWeakGlobalRef(jobj)); + } + } + } + return jobj; + } static void registrationStateChange(LinphoneCore *lc, LinphoneProxyConfig* proxy,LinphoneRegistrationState state,const char* message) { JNIEnv *env = 0; jint result = jvm->AttachCurrentThread(&env,NULL); + jobject jproxy; if (result != 0) { ms_error("cannot attach VM"); return; @@ -478,7 +497,7 @@ public: env->CallVoidMethod(lcData->listener ,lcData->registrationStateId ,lcData->core - ,env->NewObject(lcData->proxyClass,lcData->proxyCtrId,lcData->core,(jlong)proxy) + ,(jproxy=lcData->getProxy(env,proxy,lcData->core)) ,env->CallStaticObjectMethod(lcData->registrationStateClass,lcData->registrationStateFromIntId,(jint)state), message ? env->NewStringUTF(message) : NULL); } @@ -591,19 +610,37 @@ public: ,env->NewObject(lcData->addressClass,lcData->addressCtrId,(jlong)from) ,message ? env->NewStringUTF(message) : NULL); } + jobject getChatMessage(JNIEnv *env , LinphoneChatMessage *msg){ + jobject jobj = 0; + + if (msg != NULL){ + void *up = linphone_chat_message_get_user_data(msg); + + if (up == NULL) { + jobj = env->NewObject(chatMessageClass,chatMessageCtrId,(jlong)linphone_chat_message_ref(msg)); + jobj = env->NewGlobalRef(jobj); + linphone_chat_message_set_user_data(msg,(void*)jobj); + } else { + jobj = (jobject)up; + } + } + return jobj; + } static void message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *msg) { JNIEnv *env = 0; + jobject jmsg; jint result = jvm->AttachCurrentThread(&env,NULL); if (result != 0) { ms_error("cannot attach VM"); return; } LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_get_user_data(lc); + /*note: we call linphone_chat_message_ref() because the application does not acquire the object when invoked from a callback*/ env->CallVoidMethod(lcData->listener ,lcData->messageReceivedId ,lcData->core ,env->NewObject(lcData->chatRoomClass,lcData->chatRoomCtrId,(jlong)room) - ,env->NewObject(lcData->chatMessageClass,lcData->chatMessageCtrId,(jlong)msg)); + ,(jmsg = lcData->getChatMessage(env, msg))); } static void is_composing_received(LinphoneCore *lc, LinphoneChatRoom *room) { JNIEnv *env = 0; @@ -771,6 +808,64 @@ public: LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_get_user_data(lc); env->CallVoidMethod(lcData->listener, lcData->configuringStateId, lcData->core, env->CallStaticObjectMethod(lcData->configuringStateClass,lcData->configuringStateFromIntId,(jint)status), message ? env->NewStringUTF(message) : NULL); } + + static void fileTransferProgressIndication(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, size_t progress) { + JNIEnv *env = 0; + jobject jmsg; + jint result = jvm->AttachCurrentThread(&env,NULL); + if (result != 0) { + ms_error("cannot attach VM"); + return; + } + LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_get_user_data(lc); + env->CallVoidMethod(lcData->listener, + lcData->fileTransferProgressIndicationId, + lcData->core, + (jmsg = lcData->getChatMessage(env, message)), + content ? create_java_linphone_content(env, content) : NULL, + progress); + } + + static void fileTransferSend(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, char* buff, size_t* size) { + JNIEnv *env = 0; + jobject jmsg; + size_t asking = *size; + jint result = jvm->AttachCurrentThread(&env,NULL); + if (result != 0) { + ms_error("cannot attach VM"); + return; + } + LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_get_user_data(lc); + *size = env->CallIntMethod(lcData->listener, + lcData->fileTransferSendId, + lcData->core, + (jmsg = lcData->getChatMessage(env, message)), + content ? create_java_linphone_content(env, content) : NULL, + buff ? env->NewDirectByteBuffer(buff, asking) : NULL, + asking); + } + + static void fileTransferRecv(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, const char* buff, size_t size) { + JNIEnv *env = 0; + jobject jmsg; + jint result = jvm->AttachCurrentThread(&env,NULL); + if (result != 0) { + ms_error("cannot attach VM"); + return; + } + LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_get_user_data(lc); + + jbyteArray jbytes = env->NewByteArray(size); + env->SetByteArrayRegion(jbytes, 0, size, (jbyte*)buff); + + env->CallVoidMethod(lcData->listener, + lcData->fileTransferRecvId, + lcData->core, + (jmsg = lcData->getChatMessage(env, message)), + content ? create_java_linphone_content(env, content) : NULL, + jbytes, + size); + } }; extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_newLinphoneCore(JNIEnv* env @@ -894,35 +989,37 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setDefaultProxyConfig( J ,jlong pc) { linphone_core_set_default_proxy((LinphoneCore*)lc,(LinphoneProxyConfig*)pc); } -extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_getDefaultProxyConfig( JNIEnv* env + +extern "C" jobject Java_org_linphone_core_LinphoneCoreImpl_getDefaultProxyConfig(JNIEnv* env ,jobject thiz ,jlong lc) { - LinphoneProxyConfig *config=0; + LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_get_user_data((LinphoneCore*)lc); linphone_core_get_default_proxy((LinphoneCore*)lc,&config); - return (jlong)config; -} - -static jobject getOrCreateProxy(JNIEnv* env,LinphoneProxyConfig* proxy){ - RETURN_PROXY_CONFIG_USER_DATA_OBJECT("LinphoneProxyConfigImpl", linphone_proxy_config, proxy); + if(config != 0) { + jobject jproxy = lcData->getProxy(env,config,lcData->core); + return jproxy; + } else { + return NULL; + } } extern "C" jobjectArray Java_org_linphone_core_LinphoneCoreImpl_getProxyConfigList(JNIEnv* env, jobject thiz, jlong lc) { const MSList* proxies = linphone_core_get_proxy_config_list((LinphoneCore*)lc); int proxyCount = ms_list_size(proxies); - jclass cls = env->FindClass("java/lang/Object"); + jclass cls = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneProxyConfigImpl")); jobjectArray jProxies = env->NewObjectArray(proxyCount,cls,NULL); + LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_get_user_data((LinphoneCore*)lc); for (int i = 0; i < proxyCount; i++ ) { LinphoneProxyConfig* proxy = (LinphoneProxyConfig*)proxies->data; - jobject jproxy = getOrCreateProxy(env,proxy); + jobject jproxy = lcData->getProxy(env,proxy,lcData->core); if(jproxy != NULL){ env->SetObjectArrayElement(jProxies, i, jproxy); - } else { - return NULL; } proxies = proxies->next; } + env->DeleteGlobalRef(cls); return jProxies; } @@ -932,9 +1029,7 @@ extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_addProxyConfig( JNIEnv* ,jlong lc ,jlong pc) { LinphoneProxyConfig* proxy = (LinphoneProxyConfig*)pc; - linphone_proxy_config_set_user_data(proxy, env->NewGlobalRef(jproxyCfg)); - - return (jint)linphone_core_add_proxy_config((LinphoneCore*)lc,(LinphoneProxyConfig*)pc); + return (jint)linphone_core_add_proxy_config((LinphoneCore*)lc,proxy); } extern "C" void Java_org_linphone_core_LinphoneCoreImpl_removeProxyConfig(JNIEnv* env, jobject thiz, jlong lc, jlong proxy) { @@ -1272,6 +1367,13 @@ extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_isPayloadTypeEnabled return (jboolean) linphone_core_payload_type_enabled((LinphoneCore*)lc, (PayloadType*)pt); } +extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_payloadTypeIsVbr(JNIEnv* env + ,jobject thiz + ,jlong lc + ,jlong pt) { + return (jboolean) linphone_core_payload_type_is_vbr((LinphoneCore*)lc, (PayloadType*)pt); +} + extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setPayloadTypeBitrate(JNIEnv* env ,jobject thiz ,jlong lc @@ -1287,6 +1389,42 @@ extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getPayloadTypeBitrate(JN return (jint)linphone_core_get_payload_type_bitrate((LinphoneCore*)lc,(PayloadType*)pt); } +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_enableAdaptiveRateControl(JNIEnv* env + ,jobject thiz + ,jlong lc + ,jboolean enable) { + linphone_core_enable_adaptive_rate_control((LinphoneCore*)lc, enable); +} + +extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_isAdaptiveRateControlEnabled(JNIEnv* env + ,jobject thiz + ,jlong lc + ) { + return (jboolean)linphone_core_adaptive_rate_control_enabled((LinphoneCore*)lc); +} +extern "C" jstring Java_org_linphone_core_LinphoneCoreImpl_getAdaptiveRateAlgorithm(JNIEnv* env + ,jobject thiz + ,jlong lc + ) { + const char* alg = linphone_core_get_adaptive_rate_algorithm((LinphoneCore*)lc); + if (alg) { + return env->NewStringUTF(alg); + } else { + return NULL; + } +} + +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setAdaptiveRateAlgorithm(JNIEnv* env + ,jobject thiz + ,jlong lc + ,jstring jalg) { + const char* alg = jalg?env->GetStringUTFChars(jalg, NULL):NULL; + linphone_core_set_adaptive_rate_algorithm((LinphoneCore*)lc,alg); + if (alg) env->ReleaseStringUTFChars(jalg, alg); + +} + + extern "C" void Java_org_linphone_core_LinphoneCoreImpl_enableEchoCancellation(JNIEnv* env ,jobject thiz ,jlong lc @@ -1525,11 +1663,6 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setMediaEncryptionMandat linphone_core_set_media_encryption_mandatory((LinphoneCore*)lc, yesno); } -extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_createProxyConfig(JNIEnv* env, jobject thiz, jlong lc) { - LinphoneProxyConfig* proxy = linphone_core_create_proxy_config((LinphoneCore *)lc); - return (jlong) proxy; -} - /* * Class: org_linphone_core_LinphoneCoreImpl * Method: disableChat @@ -1560,14 +1693,20 @@ extern "C" JNIEXPORT jboolean JNICALL Java_org_linphone_core_LinphoneCoreImpl_ch //ProxyConfig -extern "C" jlong Java_org_linphone_core_LinphoneProxyConfigImpl_newLinphoneProxyConfig(JNIEnv* env,jobject thiz) { - LinphoneProxyConfig* proxy = linphone_proxy_config_new(); - return (jlong) proxy; +extern "C" jlong Java_org_linphone_core_LinphoneProxyConfigImpl_createProxyConfig(JNIEnv* env, jobject thiz, jlong lc) { + LinphoneProxyConfig* proxy = linphone_core_create_proxy_config((LinphoneCore *)lc); + linphone_proxy_config_set_user_data(proxy,env->NewWeakGlobalRef(thiz)); + return (jlong) proxy; } -extern "C" void Java_org_linphone_core_LinphoneProxyConfigImpl_delete(JNIEnv* env,jobject thiz,jlong ptr) { - linphone_proxy_config_destroy((LinphoneProxyConfig*)ptr); +extern "C" void Java_org_linphone_core_LinphoneProxyConfigImpl_finalize(JNIEnv* env + ,jobject thiz + ,jlong ptr) { + LinphoneProxyConfig *proxy=(LinphoneProxyConfig*)ptr; + linphone_proxy_config_set_user_data(proxy,NULL); + linphone_proxy_config_unref(proxy); } + extern "C" void Java_org_linphone_core_LinphoneProxyConfigImpl_setIdentity(JNIEnv* env,jobject thiz,jlong proxyCfg,jstring jidentity) { const char* identity = env->GetStringUTFChars(jidentity, NULL); linphone_proxy_config_set_identity((LinphoneProxyConfig*)proxyCfg,identity); @@ -1729,6 +1868,15 @@ extern "C" jlong Java_org_linphone_core_LinphoneProxyConfigImpl_getErrorInfo(JNI return (jlong)linphone_proxy_config_get_error_info((LinphoneProxyConfig *) ptr); } +extern "C" jint Java_org_linphone_core_LinphoneProxyConfigImpl_getPublishExpires(JNIEnv* env,jobject thiz,jlong ptr) { + return (jint)linphone_proxy_config_get_publish_expires((LinphoneProxyConfig *) ptr); +} +extern "C" void Java_org_linphone_core_LinphoneProxyConfigImpl_setPublishExpires(JNIEnv* env + ,jobject thiz + ,jlong ptr + ,jint jval) { + linphone_proxy_config_set_publish_expires((LinphoneProxyConfig *) ptr, jval); +} //Auth Info extern "C" jlong Java_org_linphone_core_LinphoneAuthInfoImpl_newLinphoneAuthInfo(JNIEnv* env @@ -2395,12 +2543,11 @@ extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_getFriendByAddress(JNIE env->ReleaseStringUTFChars(jaddress, address); return (jlong) lf; } -//LinphoneChatRoom -extern "C" jlongArray Java_org_linphone_core_LinphoneChatRoomImpl_getHistory(JNIEnv* env + +extern "C" jlongArray _LinphoneChatRoomImpl_getHistory(JNIEnv* env ,jobject thiz ,jlong ptr - ,jint limit) { - MSList* history = linphone_chat_room_get_history((LinphoneChatRoom*)ptr, limit); + ,MSList* history) { int historySize = ms_list_size(history); jlongArray jHistory = env->NewLongArray(historySize); jlong *jInternalArray = env->GetLongArrayElements(jHistory, NULL); @@ -2416,6 +2563,21 @@ extern "C" jlongArray Java_org_linphone_core_LinphoneChatRoomImpl_getHistory(JNI return jHistory; } +extern "C" jlongArray Java_org_linphone_core_LinphoneChatRoomImpl_getHistoryRange(JNIEnv* env + ,jobject thiz + ,jlong ptr + ,jint start + ,jint end) { + MSList* history = linphone_chat_room_get_history_range((LinphoneChatRoom*)ptr, start, end); + return _LinphoneChatRoomImpl_getHistory(env, thiz, ptr, history); +} +extern "C" jlongArray Java_org_linphone_core_LinphoneChatRoomImpl_getHistory(JNIEnv* env + ,jobject thiz + ,jlong ptr + ,jint limit) { + MSList* history = linphone_chat_room_get_history((LinphoneChatRoom*)ptr, limit); + return _LinphoneChatRoomImpl_getHistory(env, thiz, ptr, history); +} extern "C" jlong Java_org_linphone_core_LinphoneChatRoomImpl_getPeerAddress(JNIEnv* env ,jobject thiz ,jlong ptr) { @@ -2454,6 +2616,11 @@ extern "C" jlong Java_org_linphone_core_LinphoneChatRoomImpl_createLinphoneChatM return (jlong) chatMessage; } +extern "C" jint Java_org_linphone_core_LinphoneChatRoomImpl_getHistorySize (JNIEnv* env + ,jobject thiz + ,jlong ptr) { + return (jint) linphone_chat_room_get_history_size((LinphoneChatRoom*)ptr); +} extern "C" jint Java_org_linphone_core_LinphoneChatRoomImpl_getUnreadMessagesCount(JNIEnv* env ,jobject thiz ,jlong ptr) { @@ -2495,6 +2662,57 @@ extern "C" void Java_org_linphone_core_LinphoneChatRoomImpl_destroy(JNIEnv* env linphone_chat_room_destroy((LinphoneChatRoom*)ptr); } +extern "C" jlong Java_org_linphone_core_LinphoneChatRoomImpl_createFileTransferMessage(JNIEnv* env, jobject thiz, jlong ptr, jstring jname, jstring jtype, jstring jsubtype, jint data_size) { + LinphoneContent content = {0}; + LinphoneChatMessage *message = NULL; + + content.type = (char*)env->GetStringUTFChars(jtype, NULL); + content.subtype = (char*)env->GetStringUTFChars(jsubtype, NULL); + content.name = (char*)env->GetStringUTFChars(jname, NULL); + content.size = data_size; + message = linphone_chat_room_create_file_transfer_message((LinphoneChatRoom *)ptr, &content); + env->ReleaseStringUTFChars(jtype, content.type); + env->ReleaseStringUTFChars(jsubtype, content.subtype); + env->ReleaseStringUTFChars(jname, content.name); + + return (jlong) message; +} + +extern "C" void Java_org_linphone_core_LinphoneChatRoomImpl_cancelFileTransfer(JNIEnv* env, jobject thiz, jlong ptr, jlong message) { + linphone_chat_room_cancel_file_transfer((LinphoneChatMessage *)message); +} + +extern "C" jobject Java_org_linphone_core_LinphoneChatMessageImpl_getFileTransferInformation(JNIEnv* env, jobject thiz, jlong ptr) { + const LinphoneContent *content = linphone_chat_message_get_file_transfer_information((LinphoneChatMessage *)ptr); + if (content) + return create_java_linphone_content(env, content); + return NULL; +} + +extern "C" jstring Java_org_linphone_core_LinphoneChatMessageImpl_getAppData(JNIEnv* env, jobject thiz, jlong ptr) { + const char * app_data = linphone_chat_message_get_appdata((LinphoneChatMessage *)ptr); + return app_data ? env->NewStringUTF(app_data) : NULL; +} + +extern "C" void Java_org_linphone_core_LinphoneChatMessageImpl_setAppData(JNIEnv* env, jobject thiz, jlong ptr, jstring appdata) { + const char * data = appdata ? env->GetStringUTFChars(appdata, NULL) : NULL; + linphone_chat_message_set_appdata((LinphoneChatMessage *)ptr, data); + if (appdata) + env->ReleaseStringUTFChars(appdata, data); +} + +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setFileTransferServer(JNIEnv* env, jobject thiz, jlong ptr, jstring server_url) { + const char * url = server_url ? env->GetStringUTFChars(server_url, NULL) : NULL; + linphone_core_set_file_transfer_server((LinphoneCore *)ptr, url); + if (server_url) + env->ReleaseStringUTFChars(server_url, url); +} + +extern "C" jstring Java_org_linphone_core_LinphoneCoreImpl_getFileTransferServer(JNIEnv* env, jobject thiz, jlong ptr) { + const char * server_url = linphone_core_get_file_transfer_server((LinphoneCore *)ptr); + return server_url ? env->NewStringUTF(server_url) : NULL; +} + extern "C" void Java_org_linphone_core_LinphoneChatMessageImpl_store(JNIEnv* env ,jobject thiz ,jlong ptr) { @@ -2559,6 +2777,12 @@ extern "C" jlong Java_org_linphone_core_LinphoneChatMessageImpl_getFrom(JNIEnv* return (jlong) linphone_chat_message_get_from((LinphoneChatMessage*)ptr); } +extern "C" jlong Java_org_linphone_core_LinphoneChatMessageImpl_getTo(JNIEnv* env + ,jobject thiz + ,jlong ptr) { + return (jlong) linphone_chat_message_get_to((LinphoneChatMessage*)ptr); +} + extern "C" jlong Java_org_linphone_core_LinphoneChatMessageImpl_getPeerAddress(JNIEnv* env ,jobject thiz ,jlong ptr) { @@ -2676,6 +2900,13 @@ extern "C" void Java_org_linphone_core_LinphoneChatRoomImpl_sendMessage2(JNIEnv* linphone_chat_room_send_message2((LinphoneChatRoom*)chatroom_ptr, (LinphoneChatMessage*)messagePtr, chat_room_impl_callback, (void*)listener); } +extern "C" void Java_org_linphone_core_LinphoneChatMessageImpl_startFileDownload(JNIEnv* env, jobject thiz, jlong ptr, jobject jlistener) { + jobject listener = env->NewGlobalRef(jlistener); + LinphoneChatMessage * message = (LinphoneChatMessage *)ptr; + message->cb_ud = listener; + linphone_chat_message_start_file_download(message, chat_room_impl_callback); +} + extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setVideoWindowId(JNIEnv* env ,jobject thiz ,jlong lc @@ -3024,6 +3255,19 @@ JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneProxyConfigImpl_getQual return jvalue; } +JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneProxyConfigImpl_setRealm(JNIEnv *env, jobject thiz, jlong ptr, jstring jrealm) { + if (jrealm){ + const char *realm=env->GetStringUTFChars(jrealm, NULL); + linphone_proxy_config_set_realm((LinphoneProxyConfig *)ptr, realm); + env->ReleaseStringUTFChars(jrealm,realm); + } +} + +JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneProxyConfigImpl_getRealm(JNIEnv *env, jobject thiz, jlong ptr) { + jstring jvalue = env->NewStringUTF(linphone_proxy_config_get_realm((LinphoneProxyConfig *)ptr)); + return jvalue; +} + extern "C" jint Java_org_linphone_core_LinphoneCallImpl_getDuration(JNIEnv* env,jobject thiz,jlong ptr) { return (jint)linphone_call_get_duration((LinphoneCall *) ptr); } @@ -3293,6 +3537,60 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_tunnelAddServerAndMirror env->ReleaseStringUTFChars(jHost, cHost); } +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_tunnelAddServer(JNIEnv *env, jobject thiz, jlong pCore, jobject config) { + LinphoneTunnel *tunnel = linphone_core_get_tunnel((LinphoneCore *)pCore); + if(tunnel != NULL) { + jclass TunnelConfigClass = env->FindClass("org/linphone/core/TunnelConfig"); + jmethodID getHostMethod = env->GetMethodID(TunnelConfigClass, "getHost", "()Ljava/lang/String;"); + jmethodID getPortMethod = env->GetMethodID(TunnelConfigClass, "getPort", "()I"); + jmethodID getRemoteUdpMirrorPortMethod = env->GetMethodID(TunnelConfigClass, "getRemoteUdpMirrorPort", "()I"); + jmethodID getDelayMethod = env->GetMethodID(TunnelConfigClass, "getDelay", "()I"); + jstring hostString = (jstring)env->CallObjectMethod(config, getHostMethod); + const char *host = env->GetStringUTFChars(hostString, NULL); + if(host == NULL || strlen(host)==0) { + ms_error("LinphoneCore.tunnelAddServer(): no tunnel host defined"); + } + LinphoneTunnelConfig *tunnelConfig = linphone_tunnel_config_new(); + linphone_tunnel_config_set_host(tunnelConfig, host); + linphone_tunnel_config_set_port(tunnelConfig, env->CallIntMethod(config, getPortMethod)); + linphone_tunnel_config_set_remote_udp_mirror_port(tunnelConfig, env->CallIntMethod(config, getRemoteUdpMirrorPortMethod)); + linphone_tunnel_config_set_delay(tunnelConfig, env->CallIntMethod(config, getDelayMethod)); + linphone_tunnel_add_server(tunnel, tunnelConfig); + env->ReleaseStringUTFChars(hostString, host); + } else { + ms_error("LinphoneCore.tunnelAddServer(): tunnel feature is not enabled"); + } +} + +extern "C" jobjectArray Java_org_linphone_core_LinphoneCoreImpl_tunnelGetServers(JNIEnv *env, jobject thiz, jlong pCore) { + LinphoneTunnel *tunnel = linphone_core_get_tunnel((LinphoneCore *)pCore); + jclass TunnelConfigClass = env->FindClass("org/linphone/core/TunnelConfig"); + jmethodID setHostMethod = env->GetMethodID(TunnelConfigClass, "setHost", "(Ljava/lang/String;)V"); + jmethodID setPortMethod = env->GetMethodID(TunnelConfigClass, "setPort", "(I)V"); + jmethodID setRemoteUdpMirrorPortMethod = env->GetMethodID(TunnelConfigClass, "setRemoteUdpMirrorPort", "(I)V"); + jmethodID setDelayMethod = env->GetMethodID(TunnelConfigClass, "setDelay", "(I)V"); + jobjectArray tunnelConfigArray = NULL; + + if(tunnel != NULL) { + const MSList *servers = linphone_tunnel_get_servers(tunnel); + const MSList *it; + int i; + ms_message("servers=%p", (void *)servers); + ms_message("taille=%i", ms_list_size(servers)); + tunnelConfigArray = env->NewObjectArray(ms_list_size(servers), TunnelConfigClass, NULL); + for(it = servers, i=0; it != NULL; it = it->next, i++) { + const LinphoneTunnelConfig *conf = (const LinphoneTunnelConfig *)it->data; + jobject elt = env->AllocObject(TunnelConfigClass); + env->CallVoidMethod(elt, setHostMethod, env->NewStringUTF(linphone_tunnel_config_get_host(conf))); + env->CallVoidMethod(elt, setPortMethod, linphone_tunnel_config_get_port(conf)); + env->CallVoidMethod(elt, setRemoteUdpMirrorPortMethod, linphone_tunnel_config_get_remote_udp_mirror_port(conf)); + env->CallVoidMethod(elt, setDelayMethod, linphone_tunnel_config_get_delay(conf)); + env->SetObjectArrayElement(tunnelConfigArray, i, elt); + } + } + return tunnelConfigArray; +} + extern "C" void Java_org_linphone_core_LinphoneCoreImpl_tunnelSetHttpProxy(JNIEnv *env,jobject thiz,jlong pCore, jstring jHost, jint port, jstring username, jstring password) { @@ -3323,6 +3621,37 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_tunnelEnable(JNIEnv *env linphone_tunnel_enable(tunnel, enable); } +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_tunnelSetMode(JNIEnv *env, jobject thiz, jlong pCore, jint mode) { + LinphoneTunnel *tunnel = ((LinphoneCore *)pCore)->tunnel; + if(tunnel != NULL) { + linphone_tunnel_set_mode(tunnel, (LinphoneTunnelMode)mode); + } +} + +extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_tunnelGetMode(JNIEnv *env, jobject thiz, jlong pCore) { + LinphoneTunnel *tunnel = ((LinphoneCore *)pCore)->tunnel; + if(tunnel != NULL) { + return (jint)linphone_tunnel_get_mode(tunnel); + } else { + return 0; + } +} + +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_tunnelEnableSip(JNIEnv *env, jobject thiz, jlong pCore, jboolean enable) { + LinphoneTunnel *tunnel = ((LinphoneCore *)pCore)->tunnel; + if(tunnel != NULL) { + linphone_tunnel_enable_sip(tunnel, (bool_t)enable); + } +} + +extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_tunnelSipEnabled(JNIEnv *env, jobject thiz, jlong pCore) { + LinphoneTunnel *tunnel = ((LinphoneCore *)pCore)->tunnel; + if(tunnel != NULL) { + return (jboolean)linphone_tunnel_sip_enabled(tunnel); + } else { + return JNI_FALSE; + } +} extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setUserAgent(JNIEnv *env,jobject thiz,jlong pCore, jstring name, jstring version){ const char* cname=env->GetStringUTFChars(name, NULL); @@ -3363,6 +3692,14 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setCpuCountNative(JNIEnv ms_set_cpu_count(count); } +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setAudioJittcomp(JNIEnv *env, jobject thiz, jlong lc, jint value) { + linphone_core_set_audio_jittcomp((LinphoneCore *)lc, value); +} + +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setVideoJittcomp(JNIEnv *env, jobject thiz, jlong lc, jint value) { + linphone_core_set_video_jittcomp((LinphoneCore *)lc, value); +} + extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setAudioPort(JNIEnv *env, jobject thiz, jlong lc, jint port) { linphone_core_set_audio_port((LinphoneCore *)lc, port); } @@ -3383,6 +3720,13 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setAudioDscp(JNIEnv* env linphone_core_set_audio_dscp((LinphoneCore*)ptr,dscp); } +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setAndroidPowerManager(JNIEnv *env, jclass cls, jobject pm) { +#ifdef ANDROID + if(pm != NULL) bellesip_wake_lock_init(env, pm); + else bellesip_wake_lock_uninit(env); +#endif +} + extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getAudioDscp(JNIEnv* env,jobject thiz,jlong ptr){ return linphone_core_get_audio_dscp((LinphoneCore*)ptr); } @@ -3629,22 +3973,25 @@ extern "C" jintArray Java_org_linphone_core_LpConfigImpl_getIntRange(JNIEnv *env static jobject create_java_linphone_content(JNIEnv *env, const LinphoneContent *content){ jclass contentClass; jmethodID ctor; - jstring jtype, jsubtype, jencoding; - jbyteArray jdata=NULL; + jstring jtype, jsubtype, jencoding, jname; + jbyteArray jdata = NULL; + jint jsize = 0; contentClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneContentImpl")); - ctor = env->GetMethodID(contentClass,"", "(Ljava/lang/String;Ljava/lang/String;[BLjava/lang/String;)V"); + ctor = env->GetMethodID(contentClass,"", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[BLjava/lang/String;I)V"); - jtype=env->NewStringUTF(content->type); - jsubtype=env->NewStringUTF(content->subtype); - jencoding=content->encoding ? env->NewStringUTF(content->encoding) : NULL; + jtype = env->NewStringUTF(content->type); + jsubtype = env->NewStringUTF(content->subtype); + jencoding = content->encoding ? env->NewStringUTF(content->encoding) : NULL; + jname = content->name ? env->NewStringUTF(content->name) : NULL; + jsize = (jint) content->size; if (content->data){ - jdata=env->NewByteArray(content->size); - env->SetByteArrayRegion(jdata,0,content->size,(jbyte*)content->data); + jdata = env->NewByteArray(content->size); + env->SetByteArrayRegion(jdata, 0, content->size, (jbyte*)content->data); } - jobject jobj=env->NewObject(contentClass,ctor,jtype, jsubtype, jdata,jencoding); + jobject jobj = env->NewObject(contentClass, ctor, jname, jtype, jsubtype, jdata, jencoding, jsize); env->DeleteGlobalRef(contentClass); return jobj; } diff --git a/coreapi/linphonefriend.h b/coreapi/linphonefriend.h index 891bf7631..f64286c0e 100644 --- a/coreapi/linphonefriend.h +++ b/coreapi/linphonefriend.h @@ -356,7 +356,8 @@ LINPHONE_PUBLIC void linphone_core_reject_subscriber(LinphoneCore *lc, LinphoneF /** * Get Buddy list of LinphoneFriend - * @param lc #LinphoneCore object + * @param[in] lc #LinphoneCore object + * @return \mslist{LinphoneFriend} */ LINPHONE_PUBLIC const MSList * linphone_core_get_friend_list(const LinphoneCore *lc); diff --git a/coreapi/linphonepresence.h b/coreapi/linphonepresence.h index 780ae22b6..014821328 100644 --- a/coreapi/linphonepresence.h +++ b/coreapi/linphonepresence.h @@ -752,7 +752,7 @@ LINPHONE_PUBLIC void linphone_presence_model_set_user_data(LinphonePresenceModel * @param[in] model The #LinphonePresenceModel object for which to get the user data. * @return A pointer to the user data. */ -LINPHONE_PUBLIC void * linphone_presence_model_get_user_data(LinphonePresenceModel *model); +LINPHONE_PUBLIC void * linphone_presence_model_get_user_data(const LinphonePresenceModel *model); /** * Increase the reference count of the #LinphonePresenceService object. @@ -780,7 +780,7 @@ LINPHONE_PUBLIC void linphone_presence_service_set_user_data(LinphonePresenceSer * @param[in] service The #LinphonePresenceService object for which to get the user data. * @return A pointer to the user data. */ -LINPHONE_PUBLIC void * linphone_presence_service_get_user_data(LinphonePresenceService *service); +LINPHONE_PUBLIC void * linphone_presence_service_get_user_data(const LinphonePresenceService *service); /** * Increase the reference count of the #LinphonePresencePerson object. @@ -808,7 +808,7 @@ LINPHONE_PUBLIC void linphone_presence_person_set_user_data(LinphonePresencePers * @param[in] person The #LinphonePresencePerson object for which to get the user data. * @return A pointer to the user data. */ -LINPHONE_PUBLIC void * linphone_presence_person_get_user_data(LinphonePresencePerson *person); +LINPHONE_PUBLIC void * linphone_presence_person_get_user_data(const LinphonePresencePerson *person); /** * Increase the reference count of the #LinphonePresenceActivity object. @@ -836,7 +836,7 @@ LINPHONE_PUBLIC void linphone_presence_activity_set_user_data(LinphonePresenceAc * @param[in] activity The #LinphonePresenceActivity object for which to get the user data. * @return A pointer to the user data. */ -LINPHONE_PUBLIC void * linphone_presence_activity_get_user_data(LinphonePresenceActivity *activity); +LINPHONE_PUBLIC void * linphone_presence_activity_get_user_data(const LinphonePresenceActivity *activity); /** * Increase the reference count of the #LinphonePresenceNote object. @@ -864,7 +864,7 @@ LINPHONE_PUBLIC void linphone_presence_note_set_user_data(LinphonePresenceNote * * @param[in] note The #LinphonePresenceNote object for which to get the user data. * @return A pointer to the user data. */ -LINPHONE_PUBLIC void * linphone_presence_note_get_user_data(LinphonePresenceNote *note); +LINPHONE_PUBLIC void * linphone_presence_note_get_user_data(const LinphonePresenceNote *note); /***************************************************************************** diff --git a/coreapi/lpc2xml.c b/coreapi/lpc2xml.c index 46a71a2b9..1446a94cc 100644 --- a/coreapi/lpc2xml.c +++ b/coreapi/lpc2xml.c @@ -29,7 +29,7 @@ struct _lpc2xml_context { const LpConfig *lpc; lpc2xml_function cbf; void *ctx; - + xmlDoc *doc; char errorBuffer[LPC2XML_BZ]; char warningBuffer[LPC2XML_BZ]; @@ -42,7 +42,7 @@ lpc2xml_context* lpc2xml_context_new(lpc2xml_function cbf, void *ctx) { xmlCtx->lpc = NULL; xmlCtx->cbf = cbf; xmlCtx->ctx = ctx; - + xmlCtx->doc = NULL; xmlCtx->errorBuffer[0]='\0'; xmlCtx->warningBuffer[0]='\0'; @@ -64,8 +64,8 @@ static void lpc2xml_context_clear_logs(lpc2xml_context *ctx) { } static void lpc2xml_log(lpc2xml_context *xmlCtx, int level, const char *fmt, ...) { - va_list args; - va_start(args, fmt); + va_list args; + va_start(args, fmt); if(xmlCtx->cbf != NULL) { xmlCtx->cbf((xmlCtx)->ctx, level, fmt, args); } @@ -75,8 +75,8 @@ static void lpc2xml_log(lpc2xml_context *xmlCtx, int level, const char *fmt, ... static void lpc2xml_genericxml_error(void *ctx, const char *fmt, ...) { lpc2xml_context *xmlCtx = (lpc2xml_context *)ctx; int sl = strlen(xmlCtx->errorBuffer); - va_list args; - va_start(args, fmt); + va_list args; + va_start(args, fmt); vsnprintf(xmlCtx->errorBuffer + sl, LPC2XML_BZ-sl, fmt, args); va_end(args); } @@ -85,8 +85,8 @@ static void lpc2xml_genericxml_error(void *ctx, const char *fmt, ...) { static void lpc2xml_genericxml_warning(void *ctx, const char *fmt, ...) { lpc2xml_context *xmlCtx = (lpc2xml_context *)ctx; int sl = strlen(xmlCtx->warningBuffer); - va_list args; - va_start(args, fmt); + va_list args; + va_start(args, fmt); vsnprintf(xmlCtx->warningBuffer + sl, LPC2XML_BZ-sl, fmt, args); va_end(args); } @@ -114,25 +114,27 @@ struct __processSectionCtx { static void processSection_cb(const char *entry, struct __processSectionCtx *ctx) { if(ctx->ret == 0) { const char *comment = "#"; + xmlNode *node; + xmlAttr *name_attr; if (strncmp(comment, entry, strlen(comment)) == 0) { lpc2xml_log(ctx->ctx, LPC2XML_WARNING, "Skipped commented entry %s", entry); ctx->ret = 0; return; } - xmlNode *node = xmlNewChild(ctx->node, NULL, (const xmlChar *)"entry", NULL); + node = xmlNewChild(ctx->node, NULL, (const xmlChar *)"entry", NULL); if(node == NULL) { lpc2xml_log(ctx->ctx, LPC2XML_ERROR, "Can't create \"entry\" element"); ctx->ret = -1; return; } - xmlAttr *name_attr = xmlSetProp(node, (const xmlChar *)"name", (const xmlChar *)entry); + name_attr = xmlSetProp(node, (const xmlChar *)"name", (const xmlChar *)entry); if(name_attr == NULL) { lpc2xml_log(ctx->ctx, LPC2XML_ERROR, "Can't create name attribute for \"entry\" element"); ctx->ret = -1; return; } - + ctx->ret = processEntry(ctx->section, entry, node, ctx->ctx); } } @@ -154,12 +156,13 @@ struct __processConfigCtx { static void processConfig_cb(const char *section, struct __processConfigCtx *ctx) { if(ctx->ret == 0) { xmlNode *node = xmlNewChild(ctx->node, NULL, (const xmlChar *)"section", NULL); + xmlAttr *name_attr; if(node == NULL) { lpc2xml_log(ctx->ctx, LPC2XML_ERROR, "Can't create \"section\" element"); ctx->ret = -1; return; } - xmlAttr *name_attr = xmlSetProp(node, (const xmlChar *)"name", (const xmlChar *)section); + name_attr = xmlSetProp(node, (const xmlChar *)"name", (const xmlChar *)section); if(name_attr == NULL) { lpc2xml_log(ctx->ctx, LPC2XML_ERROR, "Can't create name attribute for \"section\" element"); ctx->ret = -1; @@ -177,22 +180,25 @@ static int processConfig(xmlNode *node, lpc2xml_context *ctx) { static int processDoc(xmlDoc *doc, lpc2xml_context *ctx) { int ret = 0; + xmlNs *xsi_ns; + xmlNs *lpc_ns; + xmlAttr *schemaLocation; xmlNode *root_node = xmlNewNode(NULL, (const xmlChar *)"config"); if(root_node == NULL) { lpc2xml_log(ctx, LPC2XML_ERROR, "Can't create \"config\" element"); return -1; } - xmlNs *lpc_ns = xmlNewNs(root_node, (const xmlChar *)"http://www.linphone.org/xsds/lpconfig.xsd", NULL); + lpc_ns = xmlNewNs(root_node, (const xmlChar *)"http://www.linphone.org/xsds/lpconfig.xsd", NULL); if(lpc_ns == NULL) { lpc2xml_log(ctx, LPC2XML_WARNING, "Can't create lpc namespace"); } else { xmlSetNs(root_node, lpc_ns); } - xmlNs *xsi_ns = xmlNewNs(root_node, (const xmlChar *)"http://www.w3.org/2001/XMLSchema-instance", (const xmlChar *)"xsi"); + xsi_ns = xmlNewNs(root_node, (const xmlChar *)"http://www.w3.org/2001/XMLSchema-instance", (const xmlChar *)"xsi"); if(lpc_ns == NULL) { lpc2xml_log(ctx, LPC2XML_WARNING, "Can't create xsi namespace"); } - xmlAttr *schemaLocation = xmlNewNsProp(root_node, xsi_ns, (const xmlChar *)"schemaLocation", (const xmlChar *)"http://www.linphone.org/xsds/lpconfig.xsd lpconfig.xsd"); + schemaLocation = xmlNewNsProp(root_node, xsi_ns, (const xmlChar *)"schemaLocation", (const xmlChar *)"http://www.linphone.org/xsds/lpconfig.xsd lpconfig.xsd"); if(schemaLocation == NULL) { lpc2xml_log(ctx, LPC2XML_WARNING, "Can't create schemaLocation"); } @@ -203,12 +209,13 @@ static int processDoc(xmlDoc *doc, lpc2xml_context *ctx) { static int internal_convert_lpc2xml(lpc2xml_context *ctx) { int ret = 0; + xmlDoc *doc; lpc2xml_log(ctx, LPC2XML_DEBUG, "Generation started"); if(ctx->doc != NULL) { xmlFreeDoc(ctx->doc); ctx->doc = NULL; } - xmlDoc *doc = xmlNewDoc((const xmlChar *)"1.0"); + doc = xmlNewDoc((const xmlChar *)"1.0"); ret = processDoc(doc, ctx); if(ret == 0) { ctx->doc = doc; @@ -226,9 +233,10 @@ int lpc2xml_set_lpc(lpc2xml_context* context, const LpConfig *lpc) { int lpc2xml_convert_file(lpc2xml_context* context, const char *filename) { int ret = -1; + xmlSaveCtxtPtr save_ctx; lpc2xml_context_clear_logs(context); xmlSetGenericErrorFunc(context, lpc2xml_genericxml_error); - xmlSaveCtxtPtr save_ctx = xmlSaveToFilename(filename, "UTF-8", XML_SAVE_FORMAT); + save_ctx = xmlSaveToFilename(filename, "UTF-8", XML_SAVE_FORMAT); if(save_ctx != NULL) { ret = internal_convert_lpc2xml(context); if(ret == 0) { @@ -248,9 +256,10 @@ int lpc2xml_convert_file(lpc2xml_context* context, const char *filename) { int lpc2xml_convert_fd(lpc2xml_context* context, int fd) { int ret = -1; + xmlSaveCtxtPtr save_ctx; lpc2xml_context_clear_logs(context); xmlSetGenericErrorFunc(context, lpc2xml_genericxml_error); - xmlSaveCtxtPtr save_ctx = xmlSaveToFd(fd, "UTF-8", XML_SAVE_FORMAT); + save_ctx = xmlSaveToFd(fd, "UTF-8", XML_SAVE_FORMAT); if(save_ctx != NULL) { ret = internal_convert_lpc2xml(context); if(ret == 0) { @@ -271,9 +280,10 @@ int lpc2xml_convert_fd(lpc2xml_context* context, int fd) { int lpc2xml_convert_string(lpc2xml_context* context, char **content) { int ret = -1; xmlBufferPtr buffer = xmlBufferCreate(); + xmlSaveCtxtPtr save_ctx; lpc2xml_context_clear_logs(context); xmlSetGenericErrorFunc(context, lpc2xml_genericxml_error); - xmlSaveCtxtPtr save_ctx = xmlSaveToBuffer(buffer, "UTF-8", XML_SAVE_FORMAT); + save_ctx = xmlSaveToBuffer(buffer, "UTF-8", XML_SAVE_FORMAT); if(save_ctx != NULL) { ret = internal_convert_lpc2xml(context); if(ret == 0) { diff --git a/coreapi/lpconfig.c b/coreapi/lpconfig.c index 9dcce9f4d..a2838d4a4 100644 --- a/coreapi/lpconfig.c +++ b/coreapi/lpconfig.c @@ -39,6 +39,12 @@ #endif #endif /*_WIN32_WCE*/ +#ifdef _MSC_VER +#include +#else +#include +#endif + #define lp_new0(type,n) (type*)calloc(sizeof(type),n) @@ -271,7 +277,7 @@ static LpSection* lp_config_parse_line(LpConfig* lpconfig, const char* line, LpS /* remove ending white spaces */ for (; pos2>pos1 && pos2[-1]==' ';pos2--) pos2[-1]='\0'; - if (pos2-pos1>=0){ + if (pos2-pos1>0){ /* found a pair key,value */ if (cur!=NULL){ @@ -457,10 +463,10 @@ int lp_config_get_int(const LpConfig *lpconfig,const char *section, const char * const char *str=lp_config_get_string(lpconfig,section,key,NULL); if (str!=NULL) { int ret=0; - + if (strstr(str,"0x")==str){ sscanf(str,"%x",&ret); - }else + }else sscanf(str,"%i",&ret); return ret; } @@ -493,14 +499,14 @@ void lp_config_set_string(LpConfig *lpconfig,const char *section, const char *ke if (sec!=NULL){ item=lp_section_find_item(sec,key); if (item!=NULL){ - if (value!=NULL) + if (value!=NULL && value[0] != '\0') lp_item_set_value(item,value); else lp_section_remove_item(sec,item); }else{ - if (value!=NULL) + if (value!=NULL && value[0] != '\0') lp_section_add_item(sec,lp_item_new(key,value)); } - }else if (value!=NULL){ + }else if (value!=NULL && value[0] != '\0'){ sec=lp_section_new(section); lp_config_add_section(lpconfig,sec); lp_section_add_item(sec,lp_item_new(key,value)); @@ -542,12 +548,19 @@ void lp_config_set_float(LpConfig *lpconfig,const char *section, const char *key void lp_item_write(LpItem *item, FILE *file){ if (item->is_comment) fprintf(file,"%s",item->value); - else + else if (item->value && item->value[0] != '\0' ) fprintf(file,"%s=%s\n",item->key,item->value); + else { + ms_warning("Not writing item %s to file, it is empty", item->key); + } } void lp_section_param_write(LpSectionParam *param, FILE *file){ - fprintf(file, " %s=%s", param->key, param->value); + if( param->value && param->value[0] != '\0') { + fprintf(file, " %s=%s", param->key, param->value); + } else { + ms_warning("Not writing param %s to file, it is empty", param->key); + } } void lp_section_write(LpSection *sec, FILE *file){ @@ -650,3 +663,57 @@ const char* lp_config_get_default_string(const LpConfig *lpconfig, const char *s return lp_config_get_string(lpconfig, default_section, key, default_value); } + +static char *_lp_config_dirname(char *path) { +#ifdef _MSC_VER + char *dir = ms_strdup(path); + PathRemoveFileSpec(dir); + return dir; +#else + char *tmp = ms_strdup(path); + char *dir = ms_strdup(dirname(tmp)); + ms_free(tmp); + return dir; +#endif +} + +void lp_config_write_relative_file(const LpConfig *lpconfig, const char *filename, const char *data) { + if(strlen(data) > 0) { + char *dir = _lp_config_dirname(lpconfig->filename); + char *filepath = ms_strdup_printf("%s/%s", dir, filename); + FILE *file = fopen(filepath, "w"); + if(file != NULL) { + fprintf(file, "%s", data); + fclose(file); + } else { + ms_error("Could not open %s for write", filepath); + } + ms_free(dir); + ms_free(filepath); + } else { + ms_warning("%s has not been created because there is no data to write", filename); + } +} + +char *lp_config_read_relative_file(const LpConfig *lpconfig, const char *filename) { + char *dir = _lp_config_dirname(lpconfig->filename); + char *filepath = ms_strdup_printf("%s/%s", dir, filename); + char *result = NULL; + if(ortp_file_exist(filepath) == 0) { + FILE *file = fopen(filepath, "r"); + if(file != NULL) { + result = ms_new0(char, MAX_LEN); + if(fgets(result, MAX_LEN, file) == NULL) { + ms_error("%s could not be loaded", filepath); + } + fclose(file); + } else { + ms_error("Could not open %s for read", filepath); + } + } else { + ms_message("%s does not exist", filepath); + } + ms_free(dir); + ms_free(filepath); + return result; +} diff --git a/coreapi/lpconfig.h b/coreapi/lpconfig.h index bd229803e..3498f00d2 100644 --- a/coreapi/lpconfig.h +++ b/coreapi/lpconfig.h @@ -272,6 +272,22 @@ LINPHONE_PUBLIC LpConfig *lp_config_ref(LpConfig *lpconfig); **/ LINPHONE_PUBLIC void lp_config_unref(LpConfig *lpconfig); +/** + * @brief Write a string in a file placed relatively with the Linphone configuration file. + * @param lpconfig LpConfig instance used as a reference + * @param filename Name of the file where to write data. The name is relative to the place of the config file + * @param data String to write + */ +LINPHONE_PUBLIC void lp_config_write_relative_file(const LpConfig *lpconfig, const char *filename, const char *data); + +/** + * @brief Read a string from a file placed relatively with the Linphone configuration file + * @param lpconfig LpConfig instance used as a reference + * @param filename Name of the file where data will be read from. The name is relative to the place of the config file + * @return The read string + */ +LINPHONE_PUBLIC char *lp_config_read_relative_file(const LpConfig *lpconfig, const char *filename); + #ifdef __cplusplus } #endif diff --git a/coreapi/message_storage.c b/coreapi/message_storage.c index 7caf4536b..c87891a34 100644 --- a/coreapi/message_storage.c +++ b/coreapi/message_storage.c @@ -37,6 +37,49 @@ static inline LinphoneChatMessage* get_transient_message(LinphoneChatRoom* cr, u return NULL; } +/* DB layout: + * | 0 | storage_id + * | 1 | type + * | 2 | subtype + * | 3 | name + * | 4 | encoding + * | 5 | size + * | 6 | data + */ +// Callback for sql request when getting linphone content +static int callback_content(void *data, int argc, char **argv, char **colName) { + LinphoneChatMessage *message = (LinphoneChatMessage *)data; + + if (message->file_transfer_information) { + linphone_content_uninit(message->file_transfer_information); + ms_free(message->file_transfer_information); + message->file_transfer_information = NULL; + } + message->file_transfer_information = (LinphoneContent *)malloc(sizeof(LinphoneContent)); + memset(message->file_transfer_information, 0, sizeof(*(message->file_transfer_information))); + + message->file_transfer_information->type = argv[1] ? ms_strdup(argv[1]) : NULL; + message->file_transfer_information->subtype = argv[2] ? ms_strdup(argv[2]) : NULL; + message->file_transfer_information->name = argv[3] ? ms_strdup(argv[3]) : NULL; + message->file_transfer_information->encoding = argv[4] ? ms_strdup(argv[4]) : NULL; + message->file_transfer_information->size = (size_t) atoi(argv[5]); + + return 0; +} + +static void fetch_content_from_database(sqlite3 *db, LinphoneChatMessage *message, int content_id) { + char* errmsg = NULL; + int ret; + char * buf; + + buf = sqlite3_mprintf("SELECT * FROM content WHERE id = %i", content_id); + ret = sqlite3_exec(db, buf, callback_content, message, &errmsg); + if (ret != SQLITE_OK) { + ms_error("Error in creation: %s.", errmsg); + sqlite3_free(errmsg); + } + sqlite3_free(buf); +} /* DB layout: * | 0 | storage_id @@ -50,10 +93,12 @@ static inline LinphoneChatMessage* get_transient_message(LinphoneChatRoom* cr, u * | 8 | external body url * | 9 | utc timestamp * | 10 | app data text + * | 11 | linphone content */ static void create_chat_message(char **argv, void *data){ LinphoneChatRoom *cr = (LinphoneChatRoom *)data; LinphoneAddress *from; + LinphoneAddress *to; unsigned int storage_id = atoi(argv[0]); @@ -65,12 +110,18 @@ static void create_chat_message(char **argv, void *data){ if(atoi(argv[3])==LinphoneChatMessageIncoming){ new_message->dir=LinphoneChatMessageIncoming; from=linphone_address_new(argv[2]); + to=linphone_address_new(argv[1]); } else { new_message->dir=LinphoneChatMessageOutgoing; from=linphone_address_new(argv[1]); + to=linphone_address_new(argv[2]); } linphone_chat_message_set_from(new_message,from); linphone_address_destroy(from); + if (to){ + linphone_chat_message_set_to(new_message,to); + linphone_address_destroy(to); + } if( argv[9] != NULL ){ new_message->time = (time_t)atol(argv[9]); @@ -83,6 +134,13 @@ static void create_chat_message(char **argv, void *data){ new_message->storage_id=storage_id; new_message->external_body_url= argv[8] ? ms_strdup(argv[8]) : NULL; new_message->appdata = argv[10]? ms_strdup(argv[10]) : NULL; + + if (argv[11] != NULL) { + int id = atoi(argv[11]); + if (id >= 0) { + fetch_content_from_database(cr->lc->db, new_message, id); + } + } } cr->messages_hist=ms_list_prepend(cr->messages_hist,new_message); } @@ -105,7 +163,7 @@ void linphone_sql_request_message(sqlite3 *db,const char *stmt,LinphoneChatRoom int ret; ret=sqlite3_exec(db,stmt,callback,cr,&errmsg); if(ret != SQLITE_OK) { - ms_error("Error in creation: %s.\n", errmsg); + ms_error("Error in creation: %s.", errmsg); sqlite3_free(errmsg); } } @@ -115,7 +173,7 @@ int linphone_sql_request(sqlite3* db,const char *stmt){ int ret; ret=sqlite3_exec(db,stmt,NULL,NULL,&errmsg); if(ret != SQLITE_OK) { - ms_error("linphone_sql_request: error sqlite3_exec(): %s.\n", errmsg); + ms_error("linphone_sql_request: statement %s -> error sqlite3_exec(): %s.", stmt, errmsg); sqlite3_free(errmsg); } return ret; @@ -127,29 +185,59 @@ void linphone_sql_request_all(sqlite3* db,const char *stmt, LinphoneCore* lc){ int ret; ret=sqlite3_exec(db,stmt,callback_all,lc,&errmsg); if(ret != SQLITE_OK) { - ms_error("linphone_sql_request_all: error sqlite3_exec(): %s.\n", errmsg); + ms_error("linphone_sql_request_all: error sqlite3_exec(): %s.", errmsg); sqlite3_free(errmsg); } } +static int linphone_chat_message_store_content(LinphoneChatMessage *msg) { + LinphoneCore *lc = linphone_chat_room_get_lc(msg->chat_room); + int id = -1; + if (lc->db) { + LinphoneContent *content = msg->file_transfer_information; + char *buf = sqlite3_mprintf("INSERT INTO content VALUES(NULL,%Q,%Q,%Q,%Q,%i,%Q);", + content->type, + content->subtype, + content->name, + content->encoding, + content->size, + NULL + ); + linphone_sql_request(lc->db, buf); + sqlite3_free(buf); + id = (unsigned int) sqlite3_last_insert_rowid (lc->db); + } + return id; +} + unsigned int linphone_chat_message_store(LinphoneChatMessage *msg){ LinphoneCore *lc=linphone_chat_room_get_lc(msg->chat_room); - int id=0; + int id = 0; if (lc->db){ - char *peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(msg->chat_room)); - char *local_contact=linphone_address_as_string_uri_only(linphone_chat_message_get_local_address(msg)); - char *buf=sqlite3_mprintf("INSERT INTO history VALUES(NULL,%Q,%Q,%i,%Q,%Q,%i,%i,%Q,%i,%Q);", + int content_id = -1; + char *peer; + char *local_contact; + char *buf; + if (msg->file_transfer_information) { + content_id = linphone_chat_message_store_content(msg); + } + + peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(msg->chat_room)); + local_contact=linphone_address_as_string_uri_only(linphone_chat_message_get_local_address(msg)); + buf=sqlite3_mprintf("INSERT INTO history VALUES(NULL,%Q,%Q,%i,%Q,%Q,%i,%i,%Q,%i,%Q,%i);", local_contact, - peer, - msg->dir, - msg->message, - "-1", /* use UTC field now */ - msg->is_read, - msg->state, - msg->external_body_url, - msg->time, - msg->appdata); + peer, + msg->dir, + msg->message, + "-1", /* use UTC field now */ + msg->is_read, + msg->state, + msg->external_body_url, + msg->time, + msg->appdata, + content_id + ); linphone_sql_request(lc->db,buf); sqlite3_free(buf); ms_free(local_contact); @@ -162,8 +250,8 @@ unsigned int linphone_chat_message_store(LinphoneChatMessage *msg){ void linphone_chat_message_store_state(LinphoneChatMessage *msg){ LinphoneCore *lc=msg->chat_room->lc; if (lc->db){ - char *buf=sqlite3_mprintf("UPDATE history SET status=%i WHERE (message = %Q OR url = %Q) AND utc = %i;", - msg->state,msg->message,msg->external_body_url,msg->time); + char *buf=sqlite3_mprintf("UPDATE history SET status=%i WHERE (id = %i) AND utc = %i;", + msg->state,msg->storage_id,msg->time); linphone_sql_request(lc->db,buf); sqlite3_free(buf); } @@ -189,11 +277,13 @@ void linphone_chat_message_store_appdata(LinphoneChatMessage* msg){ void linphone_chat_room_mark_as_read(LinphoneChatRoom *cr){ LinphoneCore *lc=linphone_chat_room_get_lc(cr); int read=1; + char *peer; + char *buf; if (lc->db==NULL) return ; - char *peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr)); - char *buf=sqlite3_mprintf("UPDATE history SET read=%i WHERE remoteContact = %Q;", + peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr)); + buf=sqlite3_mprintf("UPDATE history SET read=%i WHERE remoteContact = %Q;", read,peer); linphone_sql_request(lc->db,buf); sqlite3_free(buf); @@ -202,24 +292,28 @@ void linphone_chat_room_mark_as_read(LinphoneChatRoom *cr){ void linphone_chat_room_update_url(LinphoneChatRoom *cr, LinphoneChatMessage *msg) { LinphoneCore *lc=linphone_chat_room_get_lc(cr); + char *buf; if (lc->db==NULL) return ; - char *buf=sqlite3_mprintf("UPDATE history SET url=%Q WHERE id=%i;",msg->external_body_url,msg->storage_id); + buf=sqlite3_mprintf("UPDATE history SET url=%Q WHERE id=%i;",msg->external_body_url,msg->storage_id); linphone_sql_request(lc->db,buf); sqlite3_free(buf); } -int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr){ +static int linphone_chat_room_get_messages_count(LinphoneChatRoom *cr, bool_t unread_only){ LinphoneCore *lc=linphone_chat_room_get_lc(cr); int numrows=0; + char *peer; + char *buf; + sqlite3_stmt *selectStatement; + int returnValue; if (lc->db==NULL) return 0; - char *peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr)); - char *buf=sqlite3_mprintf("SELECT count(*) FROM history WHERE remoteContact = %Q AND read = 0;",peer); - sqlite3_stmt *selectStatement; - int returnValue = sqlite3_prepare_v2(lc->db,buf,-1,&selectStatement,NULL); + peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr)); + buf=sqlite3_mprintf("SELECT count(*) FROM history WHERE remoteContact = %Q %s;",peer,unread_only?"AND read = 0":""); + returnValue = sqlite3_prepare_v2(lc->db,buf,-1,&selectStatement,NULL); if (returnValue == SQLITE_OK){ if(sqlite3_step(selectStatement) == SQLITE_ROW){ numrows= sqlite3_column_int(selectStatement, 0); @@ -231,53 +325,85 @@ int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr){ return numrows; } +int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr){ + return linphone_chat_room_get_messages_count(cr, TRUE); +} + +int linphone_chat_room_get_history_size(LinphoneChatRoom *cr){ + return linphone_chat_room_get_messages_count(cr, FALSE); +} + void linphone_chat_room_delete_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg) { LinphoneCore *lc=cr->lc; + char *buf; if (lc->db==NULL) return ; - char *buf=sqlite3_mprintf("DELETE FROM history WHERE id = %i;", msg->storage_id); + buf=sqlite3_mprintf("DELETE FROM history WHERE id = %i;", msg->storage_id); linphone_sql_request(lc->db,buf); sqlite3_free(buf); } void linphone_chat_room_delete_history(LinphoneChatRoom *cr){ LinphoneCore *lc=cr->lc; + char *peer; + char *buf; if (lc->db==NULL) return ; - char *peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr)); - char *buf=sqlite3_mprintf("DELETE FROM history WHERE remoteContact = %Q;",peer); + peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr)); + buf=sqlite3_mprintf("DELETE FROM history WHERE remoteContact = %Q;",peer); linphone_sql_request(lc->db,buf); sqlite3_free(buf); ms_free(peer); } -MSList *linphone_chat_room_get_history(LinphoneChatRoom *cr,int nb_message){ +MSList *linphone_chat_room_get_history_range(LinphoneChatRoom *cr, int startm, int endm){ LinphoneCore *lc=linphone_chat_room_get_lc(cr); MSList *ret; char *buf; char *peer; uint64_t begin,end; + int buf_max_size = 512; if (lc->db==NULL) return NULL; - peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr)); + peer = linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr)); + cr->messages_hist = NULL; - if (nb_message > 0) - buf=sqlite3_mprintf("SELECT * FROM history WHERE remoteContact = %Q ORDER BY id DESC LIMIT %i ;",peer,nb_message); - else - buf=sqlite3_mprintf("SELECT * FROM history WHERE remoteContact = %Q ORDER BY id DESC;",peer); + + /*since we want to append query parameters depending on arguments given, we use malloc instead of sqlite3_mprintf*/ + buf=ms_malloc(buf_max_size); + buf=sqlite3_snprintf(buf_max_size-1,buf,"SELECT * FROM history WHERE remoteContact = %Q ORDER BY id DESC",peer); + + if (startm<0) startm=0; + + if (endm>0&&endm>=startm){ + buf=sqlite3_snprintf(buf_max_size-1,buf,"%s LIMIT %i ",buf,endm+1-startm); + }else if(startm>0){ + ms_message("%s(): end is lower than start (%d < %d). No end assumed.",__FUNCTION__,endm,startm); + buf=sqlite3_snprintf(buf_max_size-1,buf,"%s LIMIT -1",buf); + } + + if (startm>0){ + buf=sqlite3_snprintf(buf_max_size-1,buf,"%s OFFSET %i ",buf,startm); + } + begin=ortp_get_cur_time_ms(); linphone_sql_request_message(lc->db,buf,cr); end=ortp_get_cur_time_ms(); - ms_message("linphone_chat_room_get_history(): completed in %i ms",(int)(end-begin)); - sqlite3_free(buf); + ms_message("%s(): completed in %i ms",__FUNCTION__, (int)(end-begin)); + ms_free(buf); ret=cr->messages_hist; cr->messages_hist=NULL; ms_free(peer); return ret; } +MSList *linphone_chat_room_get_history(LinphoneChatRoom *cr,int nb_message){ + return linphone_chat_room_get_history_range(cr, 0, nb_message); +} + + void linphone_close_storage(sqlite3* db){ sqlite3_close(db); } @@ -357,8 +483,9 @@ static void linphone_migrate_timestamps(sqlite3* db){ sqlite3_free(errmsg); linphone_sql_request(db, "ROLLBACK"); } else { + uint64_t end; linphone_sql_request(db, "COMMIT"); - uint64_t end=ortp_get_cur_time_ms(); + end=ortp_get_cur_time_ms(); ms_message("Migrated message timestamps to UTC in %i ms",(int)(end-begin)); } } @@ -373,7 +500,7 @@ void linphone_update_table(sqlite3* db) { ms_message("Table already up to date: %s.", errmsg); sqlite3_free(errmsg); } else { - ms_debug("Table updated successfully for URL."); + ms_debug("Table history updated successfully for URL."); } // for UTC timestamp storage @@ -382,7 +509,7 @@ void linphone_update_table(sqlite3* db) { ms_message("Table already up to date: %s.", errmsg); sqlite3_free(errmsg); } else { - ms_debug("Table updated successfully for UTC."); + ms_debug("Table history updated successfully for UTC."); // migrate from old text-based timestamps to unix time-based timestamps linphone_migrate_timestamps(db); } @@ -393,7 +520,32 @@ void linphone_update_table(sqlite3* db) { ms_message("Table already up to date: %s.", errmsg); sqlite3_free(errmsg); } else { - ms_debug("Table updated successfully for app-specific data."); + ms_debug("Table history updated successfully for app-specific data."); + } + + // new field for linphone content storage + ret=sqlite3_exec(db,"ALTER TABLE history ADD COLUMN content INTEGER;",NULL,NULL,&errmsg); + if(ret != SQLITE_OK) { + ms_message("Table already up to date: %s.", errmsg); + sqlite3_free(errmsg); + } else { + ms_debug("Table history updated successfully for content data."); + ret = sqlite3_exec(db,"CREATE TABLE IF NOT EXISTS content (" + "id INTEGER PRIMARY KEY AUTOINCREMENT," + "type TEXT," + "subtype TEXT," + "name TEXT," + "encoding TEXT," + "size INTEGER," + "data BLOB" + ");", + 0,0,&errmsg); + if(ret != SQLITE_OK) { + ms_error("Error in creation: %s.\n", errmsg); + sqlite3_free(errmsg); + } else { + ms_debug("Table content successfully created."); + } } } @@ -477,6 +629,10 @@ MSList *linphone_chat_room_get_history(LinphoneChatRoom *cr,int nb_message){ return NULL; } +LINPHONE_PUBLIC MSList *linphone_chat_room_get_history_range(LinphoneChatRoom *cr, int begin, int end){ + return NULL; +} + void linphone_chat_room_delete_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg) { } @@ -499,4 +655,8 @@ int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr){ return 0; } +int linphone_chat_room_get_history_size(LinphoneChatRoom *cr){ + return 0; +} + #endif diff --git a/coreapi/misc.c b/coreapi/misc.c index 38b0efa5d..a91d02432 100644 --- a/coreapi/misc.c +++ b/coreapi/misc.c @@ -69,7 +69,7 @@ static bool_t payload_type_enabled(const PayloadType *pt) { return (((pt)->flags & PAYLOAD_TYPE_ENABLED)!=0); } -bool_t linphone_core_payload_type_enabled(LinphoneCore *lc, const PayloadType *pt){ +bool_t linphone_core_payload_type_enabled(LinphoneCore *lc, const LinphonePayloadType *pt){ if (ms_list_find(lc->codecs_conf.audio_codecs, (PayloadType*) pt) || ms_list_find(lc->codecs_conf.video_codecs, (PayloadType*)pt)){ return payload_type_enabled(pt); } @@ -77,12 +77,12 @@ bool_t linphone_core_payload_type_enabled(LinphoneCore *lc, const PayloadType *p return FALSE; } -bool_t linphone_core_payload_type_is_vbr(LinphoneCore *lc, const PayloadType *pt){ +bool_t linphone_core_payload_type_is_vbr(LinphoneCore *lc, const LinphonePayloadType *pt){ if (pt->type==PAYLOAD_VIDEO) return TRUE; return !!(pt->flags & PAYLOAD_TYPE_IS_VBR); } -int linphone_core_enable_payload_type(LinphoneCore *lc, PayloadType *pt, bool_t enabled){ +int linphone_core_enable_payload_type(LinphoneCore *lc, LinphonePayloadType *pt, bool_t enabled){ if (ms_list_find(lc->codecs_conf.audio_codecs,pt) || ms_list_find(lc->codecs_conf.video_codecs,pt)){ payload_type_set_enable(pt,enabled); _linphone_core_codec_config_write(lc); @@ -108,7 +108,7 @@ const char *linphone_core_get_payload_type_description(LinphoneCore *lc, Payload return NULL; } -void linphone_core_set_payload_type_bitrate(LinphoneCore *lc, PayloadType *pt, int bitrate){ +void linphone_core_set_payload_type_bitrate(LinphoneCore *lc, LinphonePayloadType *pt, int bitrate){ if (ms_list_find(lc->codecs_conf.audio_codecs, (PayloadType*) pt) || ms_list_find(lc->codecs_conf.video_codecs, (PayloadType*)pt)){ if (pt->type==PAYLOAD_VIDEO || pt->flags & PAYLOAD_TYPE_IS_VBR){ pt->normal_bitrate=bitrate*1000; @@ -131,7 +131,7 @@ static double get_audio_payload_bandwidth_from_codec_bitrate(const PayloadType * double npacket=50; double packet_size; int bitrate; - + if (strcmp(payload_type_get_mime(&payload_type_aaceld_44k), payload_type_get_mime(pt))==0) { /*special case of aac 44K because ptime= 10ms*/ npacket=100; @@ -181,7 +181,7 @@ static int get_audio_payload_bandwidth(LinphoneCore *lc, const PayloadType *pt, }else return (int)ceil(get_audio_payload_bandwidth_from_codec_bitrate(pt)/1000.0);/*rounding codec bandwidth should be avoid, specially for AMR*/ } -int linphone_core_get_payload_type_bitrate(LinphoneCore *lc, const PayloadType *pt){ +int linphone_core_get_payload_type_bitrate(LinphoneCore *lc, const LinphonePayloadType *pt){ int maxbw=get_min_bandwidth(linphone_core_get_download_bandwidth(lc), linphone_core_get_upload_bandwidth(lc)); if (pt->type==PAYLOAD_AUDIO_CONTINUOUS || pt->type==PAYLOAD_AUDIO_PACKETIZED){ @@ -209,7 +209,7 @@ void linphone_core_update_allocated_audio_bandwidth(LinphoneCore *lc){ int maxbw=get_min_bandwidth(linphone_core_get_download_bandwidth(lc), linphone_core_get_upload_bandwidth(lc)); int max_codec_bitrate=0; - + for(elem=linphone_core_get_audio_codecs(lc);elem!=NULL;elem=elem->next){ PayloadType *pt=(PayloadType*)elem->data; if (payload_type_enabled(pt)){ @@ -421,8 +421,7 @@ int linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){ ms_error("Could not obtain stun server addrinfo."); return -1; } - if (lc->vtable.display_status!=NULL) - lc->vtable.display_status(lc,_("Stun lookup in progress...")); + linphone_core_notify_display_status(lc,_("Stun lookup in progress...")); /*create the two audio and video RTP sockets, and send STUN message to our stun server */ sock1=create_socket(call->media_ports[0].rtp_port); @@ -603,8 +602,7 @@ int linphone_core_gather_ice_candidates(LinphoneCore *lc, LinphoneCall *call) ms_warning("Fail to resolve STUN server for ICE gathering."); return -1; } - if (lc->vtable.display_status != NULL) - lc->vtable.display_status(lc, _("ICE local candidates gathering in progress...")); + linphone_core_notify_display_status(lc, _("ICE local candidates gathering in progress...")); /* Gather local host candidates. */ if (linphone_core_get_local_ip_for(AF_INET, NULL, local_addr) < 0) { @@ -658,7 +656,7 @@ void linphone_core_update_ice_state_in_call_stats(LinphoneCall *call) } else { call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateFailed; } - if (call->params.has_video && (video_check_list != NULL)) { + if (call->params->has_video && (video_check_list != NULL)) { if (ice_check_list_state(video_check_list) == ICL_Completed) { switch (ice_check_list_selected_valid_candidate_type(video_check_list)) { case ICT_HostCandidate: @@ -678,12 +676,12 @@ void linphone_core_update_ice_state_in_call_stats(LinphoneCall *call) } } else if (session_state == IS_Running) { call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateInProgress; - if (call->params.has_video && (video_check_list != NULL)) { + if (call->params->has_video && (video_check_list != NULL)) { call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateInProgress; } } else { call->stats[LINPHONE_CALL_STATS_AUDIO].ice_state = LinphoneIceStateFailed; - if (call->params.has_video && (video_check_list != NULL)) { + if (call->params->has_video && (video_check_list != NULL)) { call->stats[LINPHONE_CALL_STATS_VIDEO].ice_state = LinphoneIceStateFailed; } } @@ -946,18 +944,6 @@ bool_t linphone_core_media_description_contains_video_stream(const SalMediaDescr return FALSE; } -LinphoneCall * is_a_linphone_call(void *user_pointer){ - LinphoneCall *call=(LinphoneCall*)user_pointer; - if (call==NULL) return NULL; - return call->magic==linphone_call_magic ? call : NULL; -} - -LinphoneProxyConfig * is_a_linphone_proxy_config(void *user_pointer){ - LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)user_pointer; - if (cfg==NULL) return NULL; - return cfg->magic==linphone_proxy_config_magic ? cfg : NULL; -} - unsigned int linphone_core_get_audio_features(LinphoneCore *lc){ unsigned int ret=0; const char *features=lp_config_get_string(lc->config,"sound","features",NULL); @@ -1008,7 +994,7 @@ static int get_local_ip_with_getifaddrs(int type, char *address, int size){ struct ifaddrs *ifpstart; char retaddr[LINPHONE_IPADDR_SIZE]={0}; bool_t found=FALSE; - + if (getifaddrs(&ifpstart) < 0) { return -1; } @@ -1109,6 +1095,9 @@ static int get_local_ip_for_with_connect(int type, const char *dest, char *resul int linphone_core_get_local_ip_for(int type, const char *dest, char *result){ int err; +#ifdef HAVE_GETIFADDRS + int found_ifs; +#endif strcpy(result,type==AF_INET ? "127.0.0.1" : "::1"); if (dest==NULL){ @@ -1124,8 +1113,6 @@ int linphone_core_get_local_ip_for(int type, const char *dest, char *result){ #ifdef HAVE_GETIFADDRS /*we use getifaddrs for lookup of default interface */ - int found_ifs; - found_ifs=get_local_ip_with_getifaddrs(type,result,LINPHONE_IPADDR_SIZE); if (found_ifs==1){ return 0; @@ -1137,6 +1124,26 @@ int linphone_core_get_local_ip_for(int type, const char *dest, char *result){ return 0; } +void linphone_core_get_local_ip(LinphoneCore *lc, int af, const char *dest, char *result) { + if (af == AF_UNSPEC) { + if (linphone_core_ipv6_enabled(lc)) { + bool_t has_ipv6 = linphone_core_get_local_ip_for(AF_INET6, dest, result) == 0; + if (strcmp(result, "::1") != 0) + return; /*this machine has real ipv6 connectivity*/ + if ((linphone_core_get_local_ip_for(AF_INET, dest, result) == 0) && (strcmp(result, "127.0.0.1") != 0)) + return; /*this machine has only ipv4 connectivity*/ + if (has_ipv6) { + /*this machine has only local loopback for both ipv4 and ipv6, so prefer ipv6*/ + strncpy(result, "::1", LINPHONE_IPADDR_SIZE); + return; + } + } + /*in all other cases use IPv4*/ + af = AF_INET; + } + linphone_core_get_local_ip_for(af, dest, result); +} + SalReason linphone_reason_to_sal(LinphoneReason reason){ switch(reason){ case LinphoneReasonNone: diff --git a/coreapi/player.c b/coreapi/player.c new file mode 100644 index 000000000..df1641886 --- /dev/null +++ b/coreapi/player.c @@ -0,0 +1,168 @@ + +/* +linphone +Copyright (C) 2014 Belledonne Communications SARL + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include "private.h" + +/** + * Open a new source on this player. + * @param obj the player + * @param filename file to open. + * @param cb a callback used to notify end of play. + * @param user_data a user-data provided in the callback to help the application to retrieve its context. + * @return 0 if successful, -1 otherwise +**/ +int linphone_player_open(LinphonePlayer *obj, const char *filename, LinphonePlayerEofCallback cb, void *user_data){ + obj->user_data=user_data; + obj->cb=cb; + return obj->open(obj->impl,filename); +} + +/** + * Start a play operation. The player must have been open previously with linphone_player_open(). + * @param obj the player. + * @return 0 if successful, -1 otherwise +**/ +int linphone_player_start(LinphonePlayer *obj){ + return obj->start(obj->impl); +} + +/** + * Suspend a play operation. The player must have been started previously with linphone_player_start(). + * @param obj the player. + * @return 0 if successful, -1 otherwise +**/ +int linphone_player_pause(LinphonePlayer *obj){ + return obj->pause(obj->impl); +} + +/** + * Seek at a given position given in milliseconds. The player must be in the paused state. + * @param obj the player. + * @param time_ms the position to seek to. + * @return 0 if successful, -1 otherwise +**/ +int linphone_player_seek(LinphonePlayer *obj, int time_ms){ + return obj->seek(obj->impl,time_ms); +} + +/** + * Get the state of play operation. + * @param obj the player. + * @return the state of the player within MSPlayerClosed, MSPlayerStarted, MSPlayerPaused. +**/ +MSPlayerState linphone_player_get_state(LinphonePlayer *obj){ + return obj->get_state(obj->impl); +} + +/** + * Close the player. + * @param obj the player. +**/ +void linphone_player_close(LinphonePlayer *obj){ + return obj->close(obj->impl); +} + + +/* + * Call player implementation below. + */ + + +static bool_t call_player_check_state(LinphonePlayer *player, bool_t check_player){ + LinphoneCall *call=(LinphoneCall*)player->impl; + if (call->state!=LinphoneCallStreamsRunning){ + ms_warning("Call [%p]: in-call player not usable in state [%s]",call,linphone_call_state_to_string(call->state)); + return FALSE; + } + if (call->audiostream==NULL) { + ms_error("call_player_check_state(): no audiostream."); + return FALSE; + } + if (check_player && call->audiostream->av_player.player==NULL){ + ms_error("call_player_check_state(): no player."); + return FALSE; + } + return TRUE; +} + +static void on_eof(void *user_data, MSFilter *f, unsigned int event_id, void *arg){ + LinphonePlayer *player=(LinphonePlayer *)user_data; + if (player->cb) player->cb(player,user_data); +} + +static int call_player_open(LinphonePlayer* player, const char *filename){ + LinphoneCall *call=(LinphoneCall*)player->impl; + MSFilter *filter; + if (!call_player_check_state(player,FALSE)) return -1; + filter=audio_stream_open_remote_play(call->audiostream,filename); + if (!filter) return -1; + ms_filter_add_notify_callback(filter,&on_eof,player,FALSE); + return 0; +} + +static int call_player_start(LinphonePlayer *player){ + LinphoneCall *call=(LinphoneCall*)player->impl; + if (!call_player_check_state(player,TRUE)) return -1; + return ms_filter_call_method_noarg(call->audiostream->av_player.player,MS_PLAYER_START); +} + +static int call_player_pause(LinphonePlayer *player){ + LinphoneCall *call=(LinphoneCall*)player->impl; + if (!call_player_check_state(player,TRUE)) return -1; + return ms_filter_call_method_noarg(call->audiostream->av_player.player,MS_PLAYER_PAUSE); +} + +static MSPlayerState call_player_get_state(LinphonePlayer *player){ + LinphoneCall *call=(LinphoneCall*)player->impl; + MSPlayerState state=MSPlayerClosed; + if (!call_player_check_state(player,TRUE)) return MSPlayerClosed; + ms_filter_call_method(call->audiostream->av_player.player,MS_PLAYER_GET_STATE,&state); + return state; +} + +static int call_player_seek(LinphonePlayer *player, int time_ms){ + LinphoneCall *call=(LinphoneCall*)player->impl; + if (!call_player_check_state(player,TRUE)) return -1; + return ms_filter_call_method(call->audiostream->av_player.player,MS_PLAYER_SEEK_MS,&time_ms); +} + +static void call_player_close(LinphonePlayer *player){ + LinphoneCall *call=(LinphoneCall*)player->impl; + if (!call_player_check_state(player,TRUE)) return; + ms_filter_call_method_noarg(call->audiostream->av_player.player,MS_PLAYER_CLOSE); + +} + +static void on_call_destroy(void *obj, belle_sip_object_t *call_being_destroyed){ + ms_free(obj); +} + +LinphonePlayer *linphone_call_build_player(LinphoneCall *call){ + LinphonePlayer *obj=ms_new0(LinphonePlayer,1); + obj->open=call_player_open; + obj->close=call_player_close; + obj->start=call_player_start; + obj->seek=call_player_seek; + obj->pause=call_player_pause; + obj->get_state=call_player_get_state; + obj->impl=call; + belle_sip_object_weak_ref(call,on_call_destroy,obj); + return obj; +} diff --git a/coreapi/presence.c b/coreapi/presence.c index 183002b86..53d206ea5 100644 --- a/coreapi/presence.c +++ b/coreapi/presence.c @@ -89,9 +89,9 @@ static char presence_id_valid_start_characters[] = ":_abcdefghijklmnopqrstuvwxyz static char * generate_presence_id(void) { char id[7]; int i; - id[0] = presence_id_valid_start_characters[random() % (sizeof(presence_id_valid_start_characters)-1)]; + id[0] = presence_id_valid_start_characters[ortp_random() % (sizeof(presence_id_valid_start_characters)-1)]; for (i = 1; i < 6; i++) { - id[i] = presence_id_valid_characters[random() % (sizeof(presence_id_valid_characters)-1)]; + id[i] = presence_id_valid_characters[ortp_random() % (sizeof(presence_id_valid_characters)-1)]; } id[6] = '\0'; @@ -1043,7 +1043,7 @@ void linphone_presence_model_set_user_data(LinphonePresenceModel *model, void *u model->user_data = user_data; } -void * linphone_presence_model_get_user_data(LinphonePresenceModel *model) { +void * linphone_presence_model_get_user_data(const LinphonePresenceModel *model) { return model->user_data; } @@ -1065,7 +1065,7 @@ void linphone_presence_service_set_user_data(LinphonePresenceService *service, v service->user_data = user_data; } -void * linphone_presence_service_get_user_data(LinphonePresenceService *service) { +void * linphone_presence_service_get_user_data(const LinphonePresenceService *service) { return service->user_data; } @@ -1087,7 +1087,7 @@ void linphone_presence_person_set_user_data(LinphonePresencePerson *person, void person->user_data = user_data; } -void * linphone_presence_person_get_user_data(LinphonePresencePerson *person) { +void * linphone_presence_person_get_user_data(const LinphonePresencePerson *person) { return person->user_data; } @@ -1109,7 +1109,7 @@ void linphone_presence_activity_set_user_data(LinphonePresenceActivity *activity activity->user_data = user_data; } -void * linphone_presence_activity_get_user_data(LinphonePresenceActivity *activity) { +void * linphone_presence_activity_get_user_data(const LinphonePresenceActivity *activity) { return activity->user_data; } @@ -1131,7 +1131,7 @@ void linphone_presence_note_set_user_data(LinphonePresenceNote *note, void *user note->user_data = user_data; } -void * linphone_presence_note_get_user_data(LinphonePresenceNote *note) { +void * linphone_presence_note_get_user_data(const LinphonePresenceNote *note) { return note->user_data; } @@ -1443,9 +1443,9 @@ void linphone_core_add_subscriber(LinphoneCore *lc, const char *subscriber, SalO linphone_friend_set_inc_subscribe_policy(fl,LinphoneSPAccept); fl->inc_subscribe_pending=TRUE; lc->subscribers=ms_list_append(lc->subscribers,(void *)fl); - if (lc->vtable.new_subscription_requested!=NULL) { + { char *tmp=linphone_address_as_string(fl->uri); - lc->vtable.new_subscription_requested(lc,fl,tmp); + linphone_core_notify_new_subscription_requested(lc,fl,tmp); ms_free(tmp); } } @@ -1876,8 +1876,7 @@ void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeStatus ss, Sa } lf->presence = presence; lf->subscribe_active=TRUE; - if (lc->vtable.notify_presence_received) - lc->vtable.notify_presence_received(lc,(LinphoneFriend*)lf); + linphone_core_notify_notify_presence_received(lc,(LinphoneFriend*)lf); ms_free(tmp); }else{ ms_message("But this person is not part of our friend list, so we don't care."); diff --git a/coreapi/private.h b/coreapi/private.h index aea70ebc2..d4be0c301 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -80,6 +80,8 @@ extern "C" { #endif struct _LinphoneCallParams{ + belle_sip_object_t base; + void *user_data; LinphoneCall *referer; /*in case this call creation is consecutive to an incoming transfer, this points to the original call */ int audio_bw; /* bandwidth limit for audio stream */ LinphoneMediaEncryption media_encryption; @@ -100,10 +102,14 @@ struct _LinphoneCallParams{ bool_t real_early_media; /*send real media even during early media (for outgoing calls)*/ bool_t in_conference; /*in conference mode */ bool_t low_bandwidth; + bool_t no_user_consent;/*when set to TRUE an UPDATE request will be used instead of reINVITE*/ + uint16_t avpf_rr_interval; /*in milliseconds*/ LinphonePrivacyMask privacy; - uint16_t avpf_rr_interval; }; +BELLE_SIP_DECLARE_VPTR(LinphoneCallParams); + + struct _LinphoneQualityReporting{ reporting_session_report_t * reports[2]; /**Store information on audio and video media streams (RFC 6035) */ bool_t was_video_running; /*Keep video state since last check in order to detect its (de)activation*/ @@ -111,6 +117,8 @@ struct _LinphoneQualityReporting{ }; struct _LinphoneCallLog{ + belle_sip_object_t base; + void *user_data; struct _LinphoneCore *lc; LinphoneCallDir dir; /**< The direction of the call*/ LinphoneCallStatus status; /**< The status of the call*/ @@ -119,18 +127,17 @@ struct _LinphoneCallLog{ char start_date[128]; /**config, "proxy", "reg_identity", NULL) : NULL; const char *proxy = lc ? lp_config_get_default_string(lc->config, "proxy", "reg_proxy", NULL) : NULL; const char *route = lc ? lp_config_get_default_string(lc->config, "proxy", "reg_route", NULL) : NULL; + const char *realm = lc ? lp_config_get_default_string(lc->config, "proxy", "realm", NULL) : NULL; const char *quality_reporting_collector = lc ? lp_config_get_default_string(lc->config, "proxy", "quality_reporting_collector", NULL) : NULL; const char *contact_params = lc ? lp_config_get_default_string(lc->config, "proxy", "contact_parameters", NULL) : NULL; const char *contact_uri_params = lc ? lp_config_get_default_string(lc->config, "proxy", "contact_uri_parameters", NULL) : NULL; - memset(obj, 0, sizeof(LinphoneProxyConfig)); - obj->magic = linphone_proxy_config_magic; obj->expires = lc ? lp_config_get_default_int(lc->config, "proxy", "reg_expires", 3600) : 3600; - obj->reg_sendregister = lc ? lp_config_get_default_int(lc->config, "proxy", "reg_sendregister", 0) : 0; + obj->reg_sendregister = lc ? lp_config_get_default_int(lc->config, "proxy", "reg_sendregister", 1) : 1; obj->dial_prefix = dial_prefix ? ms_strdup(dial_prefix) : NULL; obj->dial_escape_plus = lc ? lp_config_get_default_int(lc->config, "proxy", "dial_escape_plus", 0) : 0; obj->privacy = lc ? lp_config_get_default_int(lc->config, "proxy", "privacy", LinphonePrivacyDefault) : LinphonePrivacyDefault; obj->reg_identity = identity ? ms_strdup(identity) : NULL; obj->reg_proxy = proxy ? ms_strdup(proxy) : NULL; obj->reg_route = route ? ms_strdup(route) : NULL; + obj->domain = NULL; + obj->realm = realm ? ms_strdup(realm) : NULL; obj->quality_reporting_enabled = lc ? lp_config_get_default_int(lc->config, "proxy", "quality_reporting_enabled", 0) : 0; obj->quality_reporting_collector = quality_reporting_collector ? ms_strdup(quality_reporting_collector) : NULL; obj->quality_reporting_interval = lc ? lp_config_get_default_int(lc->config, "proxy", "quality_reporting_interval", 0) : 0; obj->contact_params = contact_params ? ms_strdup(contact_params) : NULL; obj->contact_uri_params = contact_uri_params ? ms_strdup(contact_uri_params) : NULL; - obj->avpf_enabled = lc ? lp_config_get_default_int(lc->config, "proxy", "avpf", 0) : 0; + obj->avpf_mode = lc ? lp_config_get_default_int(lc->config, "proxy", "avpf", LinphoneAVPFDefault) : LinphoneAVPFDefault; obj->avpf_rr_interval = lc ? lp_config_get_default_int(lc->config, "proxy", "avpf_rr_interval", 5) : 5; obj->publish_expires=-1; } @@ -131,35 +132,74 @@ LinphoneProxyConfig *linphone_proxy_config_new() { return linphone_core_create_proxy_config(NULL); } +static void _linphone_proxy_config_destroy(LinphoneProxyConfig *obj); + +BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneProxyConfig); + +BELLE_SIP_INSTANCIATE_VPTR(LinphoneProxyConfig, belle_sip_object_t, + (belle_sip_object_destroy_t)_linphone_proxy_config_destroy, + NULL, // clone + NULL, // marshal + FALSE +); + LinphoneProxyConfig * linphone_core_create_proxy_config(LinphoneCore *lc) { - LinphoneProxyConfig *obj=NULL; - obj=ms_new(LinphoneProxyConfig,1); + LinphoneProxyConfig *obj = belle_sip_object_new(LinphoneProxyConfig); linphone_proxy_config_init(lc,obj); return obj; } -/** - * Destroys a proxy config. - * - * @note: LinphoneProxyConfig that have been removed from LinphoneCore with - * linphone_core_remove_proxy_config() must not be freed. -**/ -void linphone_proxy_config_destroy(LinphoneProxyConfig *obj){ +void _linphone_proxy_config_release_ops(LinphoneProxyConfig *obj){ + if (obj->op) { + sal_op_release(obj->op); + obj->op=NULL; + } + if (obj->publish_op){ + sal_op_release(obj->publish_op); + obj->publish_op=NULL; + } +} + +void _linphone_proxy_config_destroy(LinphoneProxyConfig *obj){ if (obj->reg_proxy!=NULL) ms_free(obj->reg_proxy); if (obj->reg_identity!=NULL) ms_free(obj->reg_identity); if (obj->reg_route!=NULL) ms_free(obj->reg_route); if (obj->quality_reporting_collector!=NULL) ms_free(obj->quality_reporting_collector); if (obj->ssctx!=NULL) sip_setup_context_free(obj->ssctx); + if (obj->domain!=NULL) ms_free(obj->domain); if (obj->realm!=NULL) ms_free(obj->realm); if (obj->type!=NULL) ms_free(obj->type); if (obj->dial_prefix!=NULL) ms_free(obj->dial_prefix); - if (obj->op) sal_op_release(obj->op); - if (obj->publish_op) sal_op_release(obj->publish_op); if (obj->contact_params) ms_free(obj->contact_params); if (obj->contact_uri_params) ms_free(obj->contact_uri_params); if (obj->saved_proxy!=NULL) linphone_address_destroy(obj->saved_proxy); if (obj->saved_identity!=NULL) linphone_address_destroy(obj->saved_identity); - ms_free(obj); + _linphone_proxy_config_release_ops(obj); +} + +/** + * Destroys a proxy config. + * @deprecated + * + * @note: LinphoneProxyConfig that have been removed from LinphoneCore with + * linphone_core_remove_proxy_config() must not be freed. +**/ +void linphone_proxy_config_destroy(LinphoneProxyConfig *cfg) { + belle_sip_object_unref(cfg); +} + +void _linphone_proxy_config_release(LinphoneProxyConfig *cfg) { + _linphone_proxy_config_release_ops(cfg); + belle_sip_object_unref(cfg); +} + +LinphoneProxyConfig *linphone_proxy_config_ref(LinphoneProxyConfig *cfg) { + belle_sip_object_ref(cfg); + return cfg; +} + +void linphone_proxy_config_unref(LinphoneProxyConfig *cfg) { + belle_sip_object_unref(cfg); } /** @@ -228,10 +268,10 @@ int linphone_proxy_config_set_identity(LinphoneProxyConfig *obj, const char *ide obj->reg_identity=NULL; } obj->reg_identity=ms_strdup(identity); - if (obj->realm){ - ms_free(obj->realm); + if (obj->domain){ + ms_free(obj->domain); } - obj->realm=ms_strdup(linphone_address_get_domain(addr)); + obj->domain=ms_strdup(linphone_address_get_domain(addr)); linphone_address_destroy(addr); return 0; } @@ -240,7 +280,7 @@ int linphone_proxy_config_set_identity(LinphoneProxyConfig *obj, const char *ide } const char *linphone_proxy_config_get_domain(const LinphoneProxyConfig *cfg){ - return cfg->realm; + return cfg->domain; } /** @@ -275,14 +315,14 @@ int linphone_proxy_config_set_route(LinphoneProxyConfig *obj, const char *route) bool_t linphone_proxy_config_check(LinphoneCore *lc, LinphoneProxyConfig *obj){ if (obj->reg_proxy==NULL){ - if (lc && lc->vtable.display_warning) - lc->vtable.display_warning(lc,_("The sip proxy address you entered is invalid, it must start with \"sip:\"" + if (lc) + linphone_core_notify_display_warning(lc,_("The sip proxy address you entered is invalid, it must start with \"sip:\"" " followed by a hostname.")); return FALSE; } if (obj->reg_identity==NULL){ - if (lc && lc->vtable.display_warning) - lc->vtable.display_warning(lc,_("The sip identity you entered is invalid.\nIt should look like " + if (lc) + linphone_core_notify_display_warning(lc,_("The sip identity you entered is invalid.\nIt should look like " "sip:username@proxydomain, such as sip:alice@example.net")); return FALSE; } @@ -310,7 +350,7 @@ void linphone_proxy_config_enable_publish(LinphoneProxyConfig *obj, bool_t val){ /** * Prevent a proxy config from refreshing its registration. - * This is useful to let registrations to expire naturally (or) when the application wants to keep control on when + * This is useful to let registrations to expire naturally (or) when the application wants to keep control on when * refreshes are sent. * However, linphone_core_set_network_reachable(lc,TRUE) will always request the proxy configs to refresh their registrations. * The refreshing operations can be resumed with linphone_proxy_config_refresh_register(). @@ -409,6 +449,7 @@ void _linphone_proxy_config_unregister(LinphoneProxyConfig *obj) { static void linphone_proxy_config_register(LinphoneProxyConfig *obj){ if (obj->reg_sendregister){ LinphoneAddress* proxy=linphone_address_new(obj->reg_proxy); + LinphoneAddress* to=linphone_address_new(obj->reg_identity); char* proxy_string; LinphoneAddress *contact; ms_message("LinphoneProxyConfig [%p] about to register (LinphoneCore version: %s)",obj,linphone_core_get_version()); @@ -417,11 +458,18 @@ static void linphone_proxy_config_register(LinphoneProxyConfig *obj){ if (obj->op) sal_op_release(obj->op); obj->op=sal_op_new(obj->lc->sal); + + linphone_configure_op(obj->lc, obj->op, to, NULL, FALSE); + linphone_address_destroy(to); + if ((contact=guess_contact_for_register(obj))) { sal_op_set_contact_address(obj->op,contact); linphone_address_destroy(contact); } + sal_op_set_user_pointer(obj->op,obj); + + if (sal_register(obj->op,proxy_string,obj->reg_identity,obj->expires)==0) { linphone_proxy_config_set_state(obj,LinphoneRegistrationProgress,"Registration in progress"); } else { @@ -434,9 +482,6 @@ static void linphone_proxy_config_register(LinphoneProxyConfig *obj){ linphone_proxy_config_set_state(obj,LinphoneRegistrationCleared,"Registration cleared"); } _linphone_proxy_config_unregister(obj); - - - } } @@ -946,13 +991,16 @@ int linphone_proxy_config_done(LinphoneProxyConfig *obj) return 0; } +const char* linphone_proxy_config_get_realm(const LinphoneProxyConfig *cfg) +{ + return cfg?cfg->realm:NULL; +} void linphone_proxy_config_set_realm(LinphoneProxyConfig *cfg, const char *realm) { if (cfg->realm!=NULL) { ms_free(cfg->realm); - cfg->realm=NULL; } - if (realm!=NULL) cfg->realm=ms_strdup(realm); + cfg->realm=ms_strdup(realm); } int linphone_proxy_config_send_publish(LinphoneProxyConfig *proxy, LinphonePresenceModel *presence){ @@ -960,10 +1008,15 @@ int linphone_proxy_config_send_publish(LinphoneProxyConfig *proxy, LinphonePrese if (proxy->state==LinphoneRegistrationOk || proxy->state==LinphoneRegistrationCleared){ if (proxy->publish_op==NULL){ + LinphoneAddress *to=linphone_address_new(linphone_proxy_config_get_identity(proxy)); proxy->publish_op=sal_op_new(proxy->lc->sal); - sal_op_set_route(proxy->publish_op,proxy->reg_proxy); - sal_op_set_from(proxy->publish_op,linphone_proxy_config_get_identity(proxy)); - sal_op_set_to(proxy->publish_op,linphone_proxy_config_get_identity(proxy)); + + linphone_configure_op(proxy->lc, proxy->publish_op, + to, NULL, FALSE); + + if (to!=NULL){ + linphone_address_destroy(to); + } if (lp_config_get_int(proxy->lc->config,"sip","publish_msg_with_contact",0)){ SalAddress *addr=sal_address_new(linphone_proxy_config_get_identity(proxy)); sal_op_set_contact_address(proxy->publish_op,addr); @@ -1089,7 +1142,7 @@ int linphone_core_add_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *cfg){ ms_warning("ProxyConfig already entered, ignored."); return 0; } - lc->sip_conf.proxies=ms_list_append(lc->sip_conf.proxies,(void *)cfg); + lc->sip_conf.proxies=ms_list_append(lc->sip_conf.proxies,(void *)linphone_proxy_config_ref(cfg)); linphone_proxy_config_apply(cfg,lc); return 0; } @@ -1115,10 +1168,7 @@ void linphone_core_remove_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *cf linphone_proxy_config_edit(cfg); linphone_proxy_config_enable_register(cfg,FALSE); linphone_proxy_config_done(cfg); - linphone_proxy_config_update(cfg); /*so that it has an effect*/ - - /*as cfg no longer in proxies, unregister will never be issued*/ - _linphone_proxy_config_unregister(cfg); + linphone_proxy_config_update(cfg); } if (lc->default_proxy==cfg){ lc->default_proxy=NULL; @@ -1139,14 +1189,25 @@ void linphone_core_clear_proxy_config(LinphoneCore *lc){ ms_list_free(copy); linphone_proxy_config_write_all_to_config_file(lc); } + +static int linphone_core_get_default_proxy_config_index(LinphoneCore *lc) { + int pos = -1; + if (lc->default_proxy != NULL) { + pos = ms_list_position(lc->sip_conf.proxies, ms_list_find(lc->sip_conf.proxies, (void *)lc->default_proxy)); + } + return pos; +} + /** * Sets the default proxy. * * This default proxy must be part of the list of already entered LinphoneProxyConfig. * Toggling it as default will make LinphoneCore use the identity associated with * the proxy configuration in all incoming and outgoing calls. + * @param[in] lc LinphoneCore object + * @param[in] config The proxy configuration to use as the default one. **/ -void linphone_core_set_default_proxy(LinphoneCore *lc, LinphoneProxyConfig *config){ +void linphone_core_set_default_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *config){ /* check if this proxy is in our list */ if (config!=NULL){ if (ms_list_find(lc->sip_conf.proxies,config)==NULL){ @@ -1157,7 +1218,7 @@ void linphone_core_set_default_proxy(LinphoneCore *lc, LinphoneProxyConfig *conf } lc->default_proxy=config; if (linphone_core_ready(lc)) - lp_config_set_int(lc->config,"sip","default_proxy",linphone_core_get_default_proxy(lc,NULL)); + lp_config_set_int(lc->config,"sip","default_proxy",linphone_core_get_default_proxy_config_index(lc)); } void linphone_core_set_default_proxy_index(LinphoneCore *lc, int index){ @@ -1167,18 +1228,26 @@ void linphone_core_set_default_proxy_index(LinphoneCore *lc, int index){ /** * Returns the default proxy configuration, that is the one used to determine the current identity. + * @deprecated Use linphone_core_get_default_proxy_config() instead. **/ int linphone_core_get_default_proxy(LinphoneCore *lc, LinphoneProxyConfig **config){ - int pos=-1; if (config!=NULL) *config=lc->default_proxy; - if (lc->default_proxy!=NULL){ - pos=ms_list_position(lc->sip_conf.proxies,ms_list_find(lc->sip_conf.proxies,(void *)lc->default_proxy)); - } - return pos; + return linphone_core_get_default_proxy_config_index(lc); +} + +/** + * Returns the default proxy configuration, that is the one used to determine the current identity. + * @param[in] lc LinphoneCore object + * @return The default proxy configuration. +**/ +LinphoneProxyConfig * linphone_core_get_default_proxy_config(LinphoneCore *lc) { + return lc->default_proxy; } /** * Returns an unmodifiable list of entered proxy configurations. + * @param[in] lc The LinphoneCore object + * @return \mslist{LinphoneProxyConfig} **/ const MSList *linphone_core_get_proxy_config_list(const LinphoneCore *lc){ return lc->sip_conf.proxies; @@ -1205,6 +1274,9 @@ void linphone_proxy_config_write_to_config_file(LpConfig *config, LinphoneProxyC if (obj->reg_identity!=NULL){ lp_config_set_string(config,key,"reg_identity",obj->reg_identity); } + if (obj->realm!=NULL){ + lp_config_set_string(config,key,"realm",obj->realm); + } if (obj->contact_params!=NULL){ lp_config_set_string(config,key,"contact_parameters",obj->contact_params); } @@ -1219,7 +1291,7 @@ void linphone_proxy_config_write_to_config_file(LpConfig *config, LinphoneProxyC lp_config_set_int(config,key,"reg_expires",obj->expires); lp_config_set_int(config,key,"reg_sendregister",obj->reg_sendregister); lp_config_set_int(config,key,"publish",obj->publish); - lp_config_set_int(config, key, "avpf", obj->avpf_enabled); + lp_config_set_int(config, key, "avpf", obj->avpf_mode); lp_config_set_int(config, key, "avpf_rr_interval", obj->avpf_rr_interval); lp_config_set_int(config,key,"dial_escape_plus",obj->dial_escape_plus); lp_config_set_string(config,key,"dial_prefix",obj->dial_prefix); @@ -1259,10 +1331,10 @@ LinphoneProxyConfig *linphone_proxy_config_new_from_config_file(LinphoneCore* lc CONFIGURE_STRING_VALUE(cfg,config,key,server_addr,"reg_proxy") CONFIGURE_STRING_VALUE(cfg,config,key,route,"reg_route") + CONFIGURE_STRING_VALUE(cfg,config,key,realm,"realm") + CONFIGURE_BOOL_VALUE(cfg,config,key,quality_reporting,"quality_reporting_enabled") - CONFIGURE_STRING_VALUE(cfg,config,key,quality_reporting_collector,"quality_reporting_collector") - CONFIGURE_INT_VALUE(cfg,config,key,quality_reporting_interval,"quality_reporting_interval") CONFIGURE_STRING_VALUE(cfg,config,key,contact_parameters,"contact_parameters") @@ -1271,7 +1343,7 @@ LinphoneProxyConfig *linphone_proxy_config_new_from_config_file(LinphoneCore* lc CONFIGURE_INT_VALUE(cfg,config,key,expires,"reg_expires") CONFIGURE_BOOL_VALUE(cfg,config,key,register,"reg_sendregister") CONFIGURE_BOOL_VALUE(cfg,config,key,publish,"publish") - CONFIGURE_BOOL_VALUE(cfg,config,key,avpf,"avpf") + CONFIGURE_INT_VALUE(cfg,config,key,avpf_mode,"avpf") CONFIGURE_INT_VALUE(cfg,config,key,avpf_rr_interval,"avpf_rr_interval") CONFIGURE_INT_VALUE(cfg,config,key,dial_escape_plus,"dial_escape_plus") CONFIGURE_STRING_VALUE(cfg,config,key,dial_prefix,"dial_prefix") @@ -1298,9 +1370,9 @@ static void linphone_proxy_config_activate_sip_setup(LinphoneProxyConfig *cfg){ caps=sip_setup_context_get_capabilities(ssc); if (caps & SIP_SETUP_CAP_ACCOUNT_MANAGER){ if (sip_setup_context_login_account(ssc,cfg->reg_identity,NULL,NULL)!=0){ - if (lc->vtable.display_warning){ + { char *tmp=ms_strdup_printf(_("Could not login as %s"),cfg->reg_identity); - lc->vtable.display_warning(lc,tmp); + linphone_core_notify_display_warning(lc,tmp); ms_free(tmp); } return; @@ -1337,7 +1409,7 @@ static bool_t can_register(LinphoneProxyConfig *cfg){ #endif //BUILD_UPNP if (lc->sip_conf.register_only_when_network_is_up){ LinphoneTunnel *tunnel=linphone_core_get_tunnel(lc); - if (tunnel && linphone_tunnel_enabled(tunnel)){ + if (tunnel && linphone_tunnel_get_mode(tunnel)){ return linphone_tunnel_connected(tunnel); }else{ return lc->network_reachable; @@ -1474,12 +1546,12 @@ void linphone_account_creator_destroy(LinphoneAccountCreator *obj){ } } -void linphone_proxy_config_set_user_data(LinphoneProxyConfig *cr, void * ud) { - cr->user_data=ud; +void linphone_proxy_config_set_user_data(LinphoneProxyConfig *cfg, void *ud) { + cfg->user_data = ud; } -void * linphone_proxy_config_get_user_data(LinphoneProxyConfig *cr) { - return cr->user_data; +void * linphone_proxy_config_get_user_data(const LinphoneProxyConfig *cfg) { + return cfg->user_data; } void linphone_proxy_config_set_state(LinphoneProxyConfig *cfg, LinphoneRegistrationState state, const char *message){ @@ -1500,9 +1572,8 @@ void linphone_proxy_config_set_state(LinphoneProxyConfig *cfg, LinphoneRegistrat if (update_friends){ linphone_core_update_friends_subscriptions(lc,cfg,TRUE); } - if (lc && lc->vtable.registration_state_changed){ - lc->vtable.registration_state_changed(lc,cfg,state,message); - } + if (lc) + linphone_core_notify_registration_state_changed(lc,cfg,state,message); } else { /*state already reported*/ } @@ -1585,11 +1656,22 @@ int linphone_proxy_config_get_publish_expires(const LinphoneProxyConfig *obj) { } void linphone_proxy_config_enable_avpf(LinphoneProxyConfig *cfg, bool_t enable) { - cfg->avpf_enabled = enable; + cfg->avpf_mode=enable ? LinphoneAVPFEnabled : LinphoneAVPFDisabled; } bool_t linphone_proxy_config_avpf_enabled(LinphoneProxyConfig *cfg) { - return cfg->avpf_enabled; + if (cfg->avpf_mode==LinphoneAVPFDefault && cfg->lc){ + return linphone_core_get_avpf_mode(cfg->lc)==LinphoneAVPFEnabled; + } + return cfg->avpf_mode == LinphoneAVPFEnabled; +} + +LinphoneAVPFMode linphone_proxy_config_get_avpf_mode(const LinphoneProxyConfig *cfg){ + return cfg->avpf_mode; +} + +void linphone_proxy_config_set_avpf_mode(LinphoneProxyConfig *cfg, LinphoneAVPFMode mode){ + cfg->avpf_mode=mode; } void linphone_proxy_config_set_avpf_rr_interval(LinphoneProxyConfig *cfg, uint8_t interval) { @@ -1600,3 +1682,7 @@ void linphone_proxy_config_set_avpf_rr_interval(LinphoneProxyConfig *cfg, uint8_ uint8_t linphone_proxy_config_get_avpf_rr_interval(const LinphoneProxyConfig *cfg) { return cfg->avpf_rr_interval; } + +char* linphone_proxy_config_get_contact(const LinphoneProxyConfig *cfg) { + return sal_op_get_public_uri(cfg->op); +} diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index 63944e55d..9e2e6c7ea 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -405,15 +405,9 @@ static void update_ip(LinphoneCall * call, int stats_type) { } } -typedef struct on_action_suggested_struct{ - LinphoneCall *call; - int stats_type; -}on_action_suggested_struct_t; - static void qos_analyzer_on_action_suggested(void *user_data, int datac, const char** datav){ - on_action_suggested_struct_t * oass = (on_action_suggested_struct_t *)user_data; - LinphoneCall *call = oass->call; - reporting_session_report_t *report = call->log->reporting.reports[oass->stats_type]; + reporting_session_report_t *report = (reporting_session_report_t*)user_data; + LinphoneCall *call = report->call; char * appendbuf; int i; int ptime = -1; @@ -653,16 +647,16 @@ int linphone_reporting_publish_interval_report(LinphoneCall* call) { void linphone_reporting_call_state_updated(LinphoneCall *call){ LinphoneCallState state=linphone_call_get_state(call); + MSQosAnalyzer *analyzer; + int i; - if (! quality_reporting_enabled(call)){ + if (state == LinphoneCallReleased||!quality_reporting_enabled(call)){ return; } switch (state){ case LinphoneCallStreamsRunning:{ bool_t video_enabled=media_report_enabled(call, LINPHONE_CALL_STATS_VIDEO); - int i; MediaStream *streams[2] = {(MediaStream*) call->audiostream, (MediaStream *) call->videostream}; - MSQosAnalyzer *analyzer; for (i=0;i<2;i++){ if (streams[i]==NULL||streams[i]->rc==NULL){ @@ -673,14 +667,12 @@ void linphone_reporting_call_state_updated(LinphoneCall *call){ analyzer=ms_bitrate_controller_get_qos_analyzer(streams[i]->rc); if (analyzer){ - on_action_suggested_struct_t * oass = ms_new0(on_action_suggested_struct_t, 1); - oass->call = call; - oass->stats_type = i; + call->log->reporting.reports[i]->call=call; STR_REASSIGN(call->log->reporting.reports[i]->qos_analyzer.name, ms_strdup(ms_qos_analyzer_get_name(analyzer))); ms_qos_analyzer_set_on_action_suggested(analyzer, qos_analyzer_on_action_suggested, - oass); + call->log->reporting.reports[i]); } } linphone_reporting_update_ip(call); @@ -691,6 +683,16 @@ void linphone_reporting_call_state_updated(LinphoneCall *call){ break; } case LinphoneCallEnd:{ + MediaStream *streams[2] = {(MediaStream*) call->audiostream, (MediaStream *) call->videostream}; + for (i=0;i<2;i++){ + if (streams[i]==NULL||streams[i]->rc==NULL){ + continue; + } + analyzer=ms_bitrate_controller_get_qos_analyzer(streams[i]->rc); + if (analyzer){ + ms_qos_analyzer_set_on_action_suggested(analyzer, NULL, NULL); + } + } if (call->log->status==LinphoneCallSuccess || call->log->status==LinphoneCallAborted){ linphone_reporting_publish_session_report(call, TRUE); } diff --git a/coreapi/quality_reporting.h b/coreapi/quality_reporting.h index 319353fc0..794c78288 100644 --- a/coreapi/quality_reporting.h +++ b/coreapi/quality_reporting.h @@ -137,6 +137,7 @@ typedef struct reporting_session_report { // for internal processing time_t last_report_date; + LinphoneCall *call; } reporting_session_report_t; diff --git a/coreapi/remote_provisioning.c b/coreapi/remote_provisioning.c index abf884e95..fd5d2eb92 100644 --- a/coreapi/remote_provisioning.c +++ b/coreapi/remote_provisioning.c @@ -36,23 +36,31 @@ static void xml2lpc_callback(void *ctx, xml2lpc_log_level level, const char *fmt static void linphone_remote_provisioning_apply(LinphoneCore *lc, const char *xml) { xml2lpc_context *context = xml2lpc_context_new(xml2lpc_callback, lc); int result = xml2lpc_set_xml_string(context, xml); + char * error_msg = NULL; if (result == 0) { - result = xml2lpc_convert(context, linphone_core_get_config(lc)); + LpConfig * lpc = linphone_core_get_config(lc); + result = xml2lpc_convert(context, lpc); if (result == 0) { - lp_config_sync(linphone_core_get_config(lc)); - xml2lpc_context_destroy(context); - linphone_configuring_terminated(lc, LinphoneConfiguringSuccessful, NULL); + // if the remote provisioning added a proxy config and none was set before, set it + if (lp_config_has_section(lpc, "proxy_0") && lp_config_get_int(lpc, "sip", "default_proxy", -1) == -1){ + lp_config_set_int(lpc, "sip", "default_proxy", 0); + } + lp_config_sync(lpc); + } else { - xml2lpc_context_destroy(context); - linphone_configuring_terminated(lc, LinphoneConfiguringFailed, "xml to lpc failed"); + error_msg = "xml to lpc failed"; } } else { - xml2lpc_context_destroy(context); - linphone_configuring_terminated(lc, LinphoneConfiguringFailed, "invalid xml"); + error_msg = "invalid xml"; } + + xml2lpc_context_destroy(context); + linphone_configuring_terminated(lc + ,error_msg ? LinphoneConfiguringFailed : LinphoneConfiguringSuccessful + , error_msg); } -static int linphone_remote_provisioning_load_file( LinphoneCore* lc, const char* file_path){ +int linphone_remote_provisioning_load_file( LinphoneCore* lc, const char* file_path){ int status = -1; FILE* f = fopen(file_path, "r"); diff --git a/coreapi/sal.c b/coreapi/sal.c index 24da751b6..ff252ca3d 100644 --- a/coreapi/sal.c +++ b/coreapi/sal.c @@ -307,7 +307,7 @@ int sal_media_description_equals(const SalMediaDescription *md1, const SalMediaD int i; if (strcmp(md1->addr, md2->addr) != 0) result |= SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED; - if (md1->nb_streams != md2->nb_streams) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED; + if (md1->nb_streams != md2->nb_streams) result |= SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED; if (md1->bandwidth != md2->bandwidth) result |= SAL_MEDIA_DESCRIPTION_CODEC_CHANGED; for(i = 0; i < md1->nb_streams; ++i){ result |= sal_stream_description_equals(&md1->streams[i], &md2->streams[i]); @@ -386,6 +386,13 @@ void sal_op_add_route_address(SalOp *op, const SalAddress *address){ sal_op_set_route_address(op,address); } } +void sal_op_set_realm(SalOp *op, const char *realm){ + SalOpBase* op_base = (SalOpBase*)op; + if (op_base->realm != NULL){ + ms_free(op_base->realm); + } + op_base->realm = ms_strdup(realm); +} void sal_op_set_from(SalOp *op, const char *from){ SET_PARAM(op,from); } @@ -511,6 +518,10 @@ void __sal_op_free(SalOp *op){ ms_free(b->route); b->route=NULL; } + if (b->realm) { + ms_free(b->realm); + b->realm=NULL; + } if (b->contact_address) { sal_address_destroy(b->contact_address); } @@ -724,3 +735,9 @@ belle_sip_stack_t *sal_get_belle_sip_stack(Sal *sal) { return sal->stack; } +char* sal_op_get_public_uri(SalOp *op) { + if (op && op->refresher) { + return belle_sip_refresher_get_public_uri(op->refresher); + } + return NULL; +} diff --git a/coreapi/upnp.c b/coreapi/upnp.c index 5fcbbe065..c8082514f 100644 --- a/coreapi/upnp.c +++ b/coreapi/upnp.c @@ -607,7 +607,7 @@ int linphone_upnp_context_send_add_port_binding(UpnpContext *lupnp, UpnpPortBind mapping.remote_port = port->external_port; mapping.remote_host = ""; snprintf(description, 128, "%s %s at %s:%d", - PACKAGE_NAME, + "Linphone", (port->protocol == UPNP_IGD_IP_PROTOCOL_TCP)? "TCP": "UDP", port->local_addr, port->local_port); mapping.description = description; @@ -834,7 +834,7 @@ int linphone_upnp_call_process(LinphoneCall *call) { linphone_core_start_update_call(lc, call); break; case LinphoneCallUpdatedByRemote: - linphone_core_start_accept_call_update(lc, call); + linphone_core_start_accept_call_update(lc, call,call->prevstate,linphone_call_state_to_string(call->prevstate)); break; case LinphoneCallOutgoingInit: linphone_core_proceed_with_invite_if_ready(lc, call, NULL); diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 0daee4a7d..17653bf07 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -18,7 +18,7 @@ UI_FILES= about.ui \ audio_assistant.ui PIXMAPS= \ - stock_people.png + stock_people.png LINPHONE_ICO_RC_FILE=linphone.rc LINPHONE_ICO_FILE=linphone.ico @@ -54,7 +54,7 @@ linphone_SOURCES= \ conference.c \ config-fetching.c \ audio_assistant.c \ - linphone.h + linphone.h if BUILD_WIZARD linphone_SOURCES+= \ setupwizard.c @@ -84,7 +84,7 @@ endif AM_CFLAGS= -DIN_LINPHONE -I$(top_srcdir)/coreapi/ \ $(MEDIASTREAMER_CFLAGS) \ $(ORTP_CFLAGS) $(BELLESIP_CFLAGS) \ - $(STRICT_OPTIONS) $(LIBGTK_CFLAGS) $(LIBGTKMAC_CFLAGS) $(IPV6_CFLAGS) \ + $(STRICT_OPTIONS) $(STRICT_OPTIONS_CC) $(LIBGTK_CFLAGS) $(LIBGTKMAC_CFLAGS) $(IPV6_CFLAGS) \ $(TUNNEL_CFLAGS) \ $(SQLITE3_CFLAGS) diff --git a/gtk/audio_assistant.c b/gtk/audio_assistant.c index c394b02fa..83a89a3eb 100644 --- a/gtk/audio_assistant.c +++ b/gtk/audio_assistant.c @@ -168,11 +168,12 @@ static void dialog_click(GtkWidget *dialog, guint response_id, GtkWidget *page){ } static void calibration_finished(LinphoneCore *lc, LinphoneEcCalibratorStatus status, int delay, void *data){ + GtkWidget * dialog; + GtkWidget *speaker_page; ms_message("echo calibration finished %s.",status==LinphoneEcCalibratorDone ? "successfully" : "with faillure"); if (status==LinphoneEcCalibratorDone) ms_message("Measured delay is %i",delay); - GtkWidget * dialog; - GtkWidget *speaker_page = get_widget_from_assistant("speaker_page"); + speaker_page = get_widget_from_assistant("speaker_page"); dialog = gtk_message_dialog_new ( GTK_WINDOW(audio_assistant), @@ -208,6 +209,7 @@ void linphone_gtk_start_record_sound(GtkWidget *w, gpointer data){ AudioStream *stream = NULL; MSSndCardManager *manager = ms_snd_card_manager_get(); gboolean active=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)); + gint timeout_id; if(active){ gchar *path = get_record_file(); @@ -217,12 +219,12 @@ void linphone_gtk_start_record_sound(GtkWidget *w, gpointer data){ path,NULL,ms_snd_card_manager_get_card(manager,linphone_core_get_capture_device(lc)),FALSE); g_object_set_data(G_OBJECT(audio_assistant),"record_stream",stream); } - gint timeout_id = gtk_timeout_add(6000,(GtkFunction)linphone_gtk_stop_record,NULL); + timeout_id = gtk_timeout_add(6000,(GtkFunction)linphone_gtk_stop_record,NULL); g_object_set_data(G_OBJECT(audio_assistant),"timeout_id",GINT_TO_POINTER(timeout_id)); g_object_set_data(G_OBJECT(audio_assistant),"path",path); } else { stream = (AudioStream *)g_object_get_data(G_OBJECT(audio_assistant),"record_stream"); - gint timeout_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(audio_assistant),"timeout_id")); + timeout_id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(audio_assistant),"timeout_id")); gtk_timeout_remove(timeout_id); if(stream != NULL){ audio_stream_stop(stream); @@ -322,7 +324,7 @@ static GtkWidget *create_intro(){ static GtkWidget *create_mic_page(){ GtkWidget *vbox=gtk_table_new(3,2,FALSE); LinphoneCore *lc=linphone_gtk_get_core(); - + const char **sound_devices; GtkWidget *labelMicChoice=gtk_label_new(_("Capture device")); GtkWidget *labelMicLevel=gtk_label_new(_("Recorded volume")); GtkWidget *mic_audiolevel=gtk_progress_bar_new(); @@ -348,8 +350,8 @@ static GtkWidget *create_mic_page(){ set_widget_to_assistant("mic_audiolevel",mic_audiolevel); set_widget_to_assistant("label_audiolevel",label_audiolevel); - - const char **sound_devices=linphone_core_get_sound_devices(lc); + + sound_devices=linphone_core_get_sound_devices(lc); linphone_gtk_fill_combo_box(capture_device, sound_devices, linphone_core_get_capture_device(lc), CAP_CAPTURE); gtk_widget_show_all(vbox); @@ -370,6 +372,7 @@ static GtkWidget *create_speaker_page(){ GtkWidget *playback_device=gtk_combo_box_new(); GtkWidget *mixer_button=gtk_button_new_with_label("System sound preferences"); GtkWidget *image; + const char **sound_devices; image=gtk_image_new_from_stock(GTK_STOCK_PREFERENCES,GTK_ICON_SIZE_MENU); gtk_button_set_image(GTK_BUTTON(mixer_button),image); @@ -382,7 +385,7 @@ static GtkWidget *create_speaker_page(){ gtk_table_set_row_spacings(GTK_TABLE(vbox),10); - const char **sound_devices=linphone_core_get_sound_devices(lc); + sound_devices=linphone_core_get_sound_devices(lc); linphone_gtk_fill_combo_box(playback_device, sound_devices, linphone_core_get_playback_device(lc),CAP_PLAYBACK); gtk_widget_show_all(vbox); @@ -414,9 +417,9 @@ static GtkWidget *create_play_record_page(){ gtk_table_attach(GTK_TABLE(vbox), rec_button, 1, 2, 0, 1, GTK_SHRINK, GTK_SHRINK, 0,0); gtk_table_attach_defaults(GTK_TABLE(vbox), labelPlay, 0, 1, 1, 2); gtk_table_attach(GTK_TABLE(vbox), play_button, 1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0,0); - + gtk_widget_show_all(vbox); - + set_widget_to_assistant("rec_button",rec_button); set_widget_to_assistant("play_button",play_button); g_signal_connect(G_OBJECT(rec_button),"toggled",(GCallback)linphone_gtk_start_record_sound,vbox); @@ -480,18 +483,23 @@ void linphone_gtk_audio_assistant_apply(GtkWidget *w){ void linphone_gtk_show_audio_assistant(void){ GtkWidget *w; + GtkWidget *welcome; + GtkWidget *mic_page; + GtkWidget *speaker_page; + GtkWidget *play_record_page; + GtkWidget *end_page; if(audio_assistant!=NULL) return; w=audio_assistant=linphone_gtk_create_window("audio_assistant"); gtk_window_set_resizable (GTK_WINDOW(w), FALSE); gtk_window_set_title(GTK_WINDOW(w),_("Audio Assistant")); - - GtkWidget *welcome=create_intro(); - GtkWidget *mic_page=create_mic_page(); - GtkWidget *speaker_page=create_speaker_page(); - GtkWidget *play_record_page=create_play_record_page(); - GtkWidget *end_page=create_end_page(); + + welcome=create_intro(); + mic_page=create_mic_page(); + speaker_page=create_speaker_page(); + play_record_page=create_play_record_page(); + end_page=create_end_page(); gtk_assistant_append_page(GTK_ASSISTANT(w),welcome); gtk_assistant_set_page_type(GTK_ASSISTANT(w),welcome,GTK_ASSISTANT_PAGE_INTRO); diff --git a/gtk/calllogs.c b/gtk/calllogs.c index 7a4840aa8..a4b86240a 100644 --- a/gtk/calllogs.c +++ b/gtk/calllogs.c @@ -36,7 +36,7 @@ void call_log_selection_changed(GtkTreeView *v){ GtkTreeSelection *select; GtkTreeIter iter; GtkTreeModel *model=NULL; - + select = gtk_tree_view_get_selection(v); if (select!=NULL){ if (gtk_tree_selection_get_selected (select, &model, &iter)){ @@ -51,7 +51,7 @@ void call_log_selection_changed(GtkTreeView *v){ void linphone_gtk_call_log_chat_selected(GtkWidget *w){ GtkTreeSelection *select; GtkTreeIter iter; - + select=gtk_tree_view_get_selection(GTK_TREE_VIEW(w)); if (select!=NULL){ GtkTreeModel *model=NULL; @@ -72,7 +72,7 @@ void linphone_gtk_call_log_chat_selected(GtkWidget *w){ void linphone_gtk_call_log_add_contact(GtkWidget *w){ GtkTreeSelection *select; GtkTreeIter iter; - + select=gtk_tree_view_get_selection(GTK_TREE_VIEW(w)); if (select!=NULL){ GtkTreeModel *model=NULL; @@ -109,7 +109,7 @@ static bool_t put_selection_to_uribar(GtkWidget *treeview){ cl = (LinphoneCallLog *)pcl; la = linphone_call_log_get_dir(cl)==LinphoneCallIncoming ? linphone_call_log_get_from(cl) : linphone_call_log_get_to(cl); tmp = linphone_address_as_string(la); - if(tmp!=NULL) + if(tmp!=NULL) gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"uribar")),tmp); ms_free(tmp); return TRUE; @@ -133,7 +133,7 @@ static GtkWidget *linphone_gtk_create_call_log_menu(GtkWidget *call_log){ GtkWidget *image; GtkTreeSelection *select; GtkTreeIter iter; - + select=gtk_tree_view_get_selection(GTK_TREE_VIEW(call_log)); if (select!=NULL){ GtkTreeModel *model=NULL; @@ -202,7 +202,7 @@ void linphone_gtk_call_log_clear_missed_call(){ GtkWidget *image=gtk_image_new_from_stock(GTK_STOCK_REFRESH,GTK_ICON_SIZE_MENU); GtkWidget *l; const gchar*text=gtk_label_get_text(GTK_LABEL(linphone_gtk_get_widget(mw,"label3"))); - + l=gtk_label_new(text); gtk_box_pack_start(GTK_BOX(box),image,FALSE,FALSE,0); gtk_box_pack_start(GTK_BOX(box),l,FALSE,FALSE,0); @@ -228,7 +228,7 @@ void linphone_gtk_call_log_display_missed_call(int nb){ GtkWidget *image=gtk_image_new_from_stock(GTK_STOCK_REFRESH,GTK_ICON_SIZE_MENU); GtkWidget *l; gchar *buf; - + buf=g_markup_printf_escaped(_("Recent calls (%i)"),nb); l=gtk_label_new(NULL); gtk_label_set_markup(GTK_LABEL(l),buf); @@ -281,7 +281,9 @@ void linphone_gtk_call_log_update(GtkWidget *w){ LinphoneFriend *lf=NULL; int duration=linphone_call_log_get_duration(cl); time_t start_date_time=linphone_call_log_get_start_date(cl); - + GdkPixbuf *incoming; + GdkPixbuf *outgoing; + #if GLIB_CHECK_VERSION(2,26,0) if (start_date_time){ GDateTime *dt=g_date_time_new_from_unix_local(start_date_time); @@ -332,7 +334,7 @@ void linphone_gtk_call_log_update(GtkWidget *w){ if (status==NULL) { headtxt=g_markup_printf_escaped(_("%s\t%s"),display,start_date ? start_date : ""); logtxt=g_markup_printf_escaped( - _("%s\t" + _("%s\t" "Quality: %s\n%s\t%s\t"), addr, quality, minutes, seconds); } else { @@ -346,8 +348,8 @@ void linphone_gtk_call_log_update(GtkWidget *w){ if (start_date) g_free(start_date); gtk_tree_store_append (store,&iter,NULL); - GdkPixbuf *incoming = create_pixbuf("call_status_incoming.png"); - GdkPixbuf *outgoing = create_pixbuf("call_status_outgoing.png"); + incoming = create_pixbuf("call_status_incoming.png"); + outgoing = create_pixbuf("call_status_outgoing.png"); gtk_tree_store_set (store,&iter, 0, linphone_call_log_get_dir(cl)==LinphoneCallOutgoing ? outgoing : incoming, 1, headtxt,2,cl,-1); diff --git a/gtk/chat.c b/gtk/chat.c index 9f6e21943..c3183ad64 100644 --- a/gtk/chat.c +++ b/gtk/chat.c @@ -30,9 +30,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. const char *linphone_gtk_message_storage_get_db_file(const char *filename){ const int path_max=1024; static char *db_file=NULL; - + if (db_file) return db_file; - + db_file=(char *)malloc(path_max*sizeof(char)); if (filename==NULL) filename=CONFIG_FILE; /*try accessing a local file first if exists*/ @@ -63,7 +63,7 @@ void linphone_gtk_quit_chatroom(LinphoneChatRoom *cr) { GtkWidget *w=g_object_get_data(G_OBJECT(friendlist),"chatview"); gchar *from; GHashTable *table=g_object_get_data(G_OBJECT(w),"table"); - + g_return_if_fail(w!=NULL); gtk_notebook_remove_page(GTK_NOTEBOOK(nb),gtk_notebook_page_num(GTK_NOTEBOOK(nb),w)); linphone_chat_room_mark_as_read(cr); @@ -95,7 +95,7 @@ GtkWidget *create_tab_chat_header(LinphoneChatRoom *cr,const LinphoneAddress *ur GtkWidget *l; GtkWidget *image=gtk_image_new_from_stock(GTK_STOCK_CLOSE,GTK_ICON_SIZE_MENU); GtkWidget *b=gtk_button_new(); - + gtk_button_set_image(GTK_BUTTON(b),image); gtk_button_set_relief(GTK_BUTTON(b),GTK_RELIEF_NONE); gtk_widget_set_size_request(b,25,20); @@ -131,14 +131,15 @@ void udpate_tab_chat_header(GtkWidget *chat_view,const LinphoneAddress *uri,Linp static gboolean scroll_to_end(GtkTextView *w){ GtkTextBuffer *buffer=gtk_text_view_get_buffer(w); + GtkTextMark *mark; GtkTextIter iter; gtk_text_buffer_get_end_iter(buffer,&iter); - GtkTextMark *mark=gtk_text_buffer_create_mark(buffer,NULL,&iter,FALSE); - gtk_text_view_scroll_mark_onscreen(w,mark); + mark=gtk_text_buffer_create_mark(buffer,NULL,&iter,FALSE); + gtk_text_view_scroll_mark_onscreen(w,mark); return FALSE; } -void linphone_gtk_push_text(GtkWidget *w, const LinphoneAddress *from, +void linphone_gtk_push_text(GtkWidget *w, const LinphoneAddress *from, gboolean me,LinphoneChatRoom *cr,LinphoneChatMessage *msg, gboolean hist){ GtkTextView *text=GTK_TEXT_VIEW(linphone_gtk_get_widget(w,"textview")); GtkTextBuffer *buffer=gtk_text_view_get_buffer(text); @@ -153,7 +154,7 @@ void linphone_gtk_push_text(GtkWidget *w, const LinphoneAddress *from, struct tm *tm; int tnow_day; int tnow_year; - + gtk_text_buffer_get_start_iter(buffer,&begin); gtk_text_buffer_get_end_iter(buffer,&iter); off=gtk_text_iter_get_offset(&iter); @@ -178,7 +179,7 @@ void linphone_gtk_push_text(GtkWidget *w, const LinphoneAddress *from, case LinphoneChatMessageStateInProgress: { g_hash_table_insert(table,(gpointer)msg,GINT_TO_POINTER(gtk_text_iter_get_line(&iter))); - gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,"Sending ..",-1, + gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,"Sending ..",-1, "right","small","italic","font_grey","bg",NULL); g_object_set_data(G_OBJECT(w),"table",table); break; @@ -195,15 +196,15 @@ void linphone_gtk_push_text(GtkWidget *w, const LinphoneAddress *from, } else { strftime(buf,80,"%H:%M",tm); } - gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,buf,-1, + gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,buf,-1, "right","small","italic","font_grey",me ? "bg":NULL,NULL); break; } case LinphoneChatMessageStateNotDelivered: - gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,"Message not sent",-1, + gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,"Message not sent",-1, "right","small","italic","font_grey",me ? "bg":NULL,NULL); break; - default : gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,"Sending ..",-1, + default : gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,"Sending ..",-1, "right","small","italic","font_grey",me ? "bg":NULL,NULL); } gtk_text_buffer_get_end_iter(buffer,&iter); @@ -225,7 +226,7 @@ void update_chat_state_message(LinphoneChatMessageState state,LinphoneChatMessag GtkWidget *friendlist=linphone_gtk_get_widget(main_window,"contact_list"); GtkWidget *page=(GtkWidget*)g_object_get_data(G_OBJECT(friendlist),"chatview"); GHashTable *table=(GHashTable*)g_object_get_data(G_OBJECT(page),"table"); - + if(page!=NULL){ GtkTextView *text=GTK_TEXT_VIEW(linphone_gtk_get_widget(page,"textview")); GtkTextBuffer *b=gtk_text_view_get_buffer(text); @@ -272,7 +273,7 @@ void update_chat_state_message(LinphoneChatMessageState state,LinphoneChatMessag gtk_text_buffer_insert_with_tags_by_name(b,&iter,result,-1, "right","small","italic","font_grey","bg",NULL); g_object_set_data(G_OBJECT(page),"table",table); - } + } } static void on_chat_state_changed(LinphoneChatMessage *msg, LinphoneChatMessageState state, void *user_pointer){ @@ -330,8 +331,8 @@ void display_history_message(GtkWidget *chat_view,MSList *messages,const Linphon LinphoneChatMessage *msg=(LinphoneChatMessage *)it->data; from_str=linphone_address_as_string_uri_only(linphone_chat_message_get_from(msg)); with_str=linphone_address_as_string_uri_only(with); - linphone_gtk_push_text(chat_view,strcmp(from_str,with_str)==0? with : - linphone_chat_message_get_from(msg), + linphone_gtk_push_text(chat_view,strcmp(from_str,with_str)==0? with : + linphone_chat_message_get_from(msg), strcmp(from_str,with_str)==0? FALSE : TRUE, linphone_chat_message_get_chat_room(msg),msg,TRUE); } @@ -343,7 +344,7 @@ void display_history_message(GtkWidget *chat_view,MSList *messages,const Linphon ms_free(from_str); ms_free(with_str); linphone_gtk_free_list(messages); - } + } } void linphone_gtk_chat_add_contact(const LinphoneAddress *addr){ @@ -445,7 +446,7 @@ void linphone_gtk_load_chatroom(LinphoneChatRoom *cr,const LinphoneAddress *uri, char *uri_str=linphone_address_as_string(uri); char *uri_only=linphone_address_as_string_uri_only(uri); MSList *messages=NULL; - + if(g_strcmp0(from_str,uri_only)!=0){ GtkTextView *text_view=GTK_TEXT_VIEW(linphone_gtk_get_widget(chat_view,"textview")); GtkTextIter start; @@ -483,7 +484,7 @@ void linphone_gtk_text_received ( LinphoneCore *lc, LinphoneChatRoom *room, gboolean send=TRUE; /*GtkNotebook *notebook= ( GtkNotebook * ) linphone_gtk_get_widget ( main_window,"viewswitch" );*/ const LinphoneAddress *from= linphone_chat_message_get_from ( msg ); - + w= ( GtkWidget* ) g_object_get_data ( G_OBJECT ( friendlist ),"chatview" ); if ( w!=NULL ) { /* Chat window opened */ @@ -496,7 +497,7 @@ void linphone_gtk_text_received ( LinphoneCore *lc, LinphoneChatRoom *room, } send=FALSE; } - } else { + } else { /* Chat window closed */ #ifdef MSG_STORAGE_ENABLED send=FALSE; @@ -530,7 +531,7 @@ void linphone_gtk_text_received ( LinphoneCore *lc, LinphoneChatRoom *room, } linphone_core_play_local(lc,linphone_gtk_get_sound_path("incoming_chat.wav")); linphone_gtk_show_friends(); - + } void linphone_gtk_is_composing_received(LinphoneCore *lc, LinphoneChatRoom *room) { diff --git a/gtk/conference.c b/gtk/conference.c index 08262c771..1bfee3afc 100644 --- a/gtk/conference.c +++ b/gtk/conference.c @@ -61,9 +61,9 @@ static GtkWidget *find_conferencee_from_call(LinphoneCall *call){ GtkWidget *conferencee_box=get_conferencee_box(mw); GList *elem; GtkWidget *ret=NULL; - + if (conferencee_box==NULL) return NULL; - + if (call!=NULL){ GList *l=gtk_container_get_children(GTK_CONTAINER(conferencee_box)); for(elem=l;elem!=NULL;elem=elem->next){ @@ -87,13 +87,14 @@ static GtkWidget * create_conference_panel(void){ GtkWidget *image=create_pixmap("stopcall-small.png"); GtkWidget *box; GtkWidget *viewswitch=linphone_gtk_get_widget(mw,"viewswitch"); - + GtkWidget *participant; + gtk_button_set_image(GTK_BUTTON(button_conf),image); g_signal_connect_swapped(G_OBJECT(button_conf),"clicked",(GCallback)linphone_gtk_terminate_call,NULL); g_object_set_data(G_OBJECT(mw),"conf_frame",(gpointer)conf_frame); - + box=gtk_vbox_new(FALSE,0); - GtkWidget *participant=linphone_gtk_create_widget("main","callee_frame"); + participant=linphone_gtk_create_widget("main","callee_frame"); gtk_widget_show(participant); gtk_box_set_homogeneous(GTK_BOX(box),TRUE); init_local_participant(participant); @@ -101,7 +102,7 @@ static GtkWidget * create_conference_panel(void){ gtk_widget_show(box); g_object_set_data(G_OBJECT(mw),"conferencee_box",box); gtk_box_pack_start(GTK_BOX(conf_box),box,FALSE,FALSE,PADDING_PIXELS); - + gtk_notebook_append_page(GTK_NOTEBOOK(viewswitch),conf_frame, create_conference_label()); return conf_frame; @@ -111,19 +112,20 @@ void linphone_gtk_set_in_conference(LinphoneCall *call){ GtkWidget *mw=linphone_gtk_get_main_window(); GtkWidget *conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(mw),"conf_frame"); GtkWidget *viewswitch=linphone_gtk_get_widget(mw,"viewswitch"); - + GtkWidget *participant; + if(conf_frame==NULL){ conf_frame=create_conference_panel(); } - GtkWidget *participant=find_conferencee_from_call(call); - + participant=find_conferencee_from_call(call); + if (participant==NULL){ /*create and add it */ GtkWidget *conferencee_box=get_conferencee_box(mw); GtkWidget *sound_meter; const LinphoneAddress *addr=linphone_call_get_remote_address(call); gchar *markup; - + participant=linphone_gtk_create_widget("main","callee_frame"); gtk_widget_show(participant); if (linphone_address_get_display_name(addr)!=NULL){ @@ -140,7 +142,7 @@ void linphone_gtk_set_in_conference(LinphoneCall *call){ gtk_box_pack_start(GTK_BOX(conferencee_box),participant,FALSE,FALSE,PADDING_PIXELS); g_object_set_data_full(G_OBJECT(participant),"call",linphone_call_ref(call),(GDestroyNotify)linphone_call_unref); gtk_notebook_set_current_page(GTK_NOTEBOOK(viewswitch), - gtk_notebook_page_num(GTK_NOTEBOOK(viewswitch),conf_frame)); + gtk_notebook_page_num(GTK_NOTEBOOK(viewswitch),conf_frame)); } } @@ -153,13 +155,13 @@ void linphone_gtk_terminate_conference_participant(LinphoneCall *call){ void linphone_gtk_unset_from_conference(LinphoneCall *call){ GtkWidget *frame=find_conferencee_from_call(call); - + if (frame){ GtkWidget *mw=linphone_gtk_get_main_window(); GtkWidget *conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(mw),"conf_frame"); GtkWidget *conferencee_box=g_object_get_data(G_OBJECT(mw),"conferencee_box"); GList *children; - + g_message("Removing a participant from conference"); gtk_widget_destroy(frame); children=gtk_container_get_children(GTK_CONTAINER(conferencee_box)); diff --git a/gtk/friendlist.c b/gtk/friendlist.c index f86f8b4c6..70be2484f 100644 --- a/gtk/friendlist.c +++ b/gtk/friendlist.c @@ -198,7 +198,7 @@ void linphone_gtk_delete_history(GtkWidget *button){ GtkWidget *chat_view; LinphoneFriend *lf=NULL; GtkWidget *friendlist; - + friendlist=linphone_gtk_get_widget(w,"contact_list"); chat_view=(GtkWidget *)g_object_get_data(G_OBJECT(friendlist),"chatview"); select = gtk_tree_view_get_selection(GTK_TREE_VIEW(friendlist)); @@ -216,7 +216,7 @@ void linphone_gtk_delete_history(GtkWidget *button){ GtkTextIter start; GtkTextIter end; GtkTextBuffer *text_buffer; - + text_buffer=gtk_text_view_get_buffer(text_view); gtk_text_buffer_get_bounds(text_buffer, &start, &end); gtk_text_buffer_delete (text_buffer, &start, &end); @@ -290,7 +290,7 @@ void linphone_gtk_friend_list_set_chat_conversation(const LinphoneAddress *la){ LinphoneFriend *lf=NULL; LinphoneChatRoom *cr=NULL; GtkNotebook *notebook=(GtkNotebook *)linphone_gtk_get_widget(w,"viewswitch"); - + lf=linphone_core_find_friend(linphone_gtk_get_core(),la); if(lf==NULL){ cr=linphone_gtk_create_chatroom(la); @@ -331,7 +331,7 @@ void linphone_gtk_friend_list_set_chat_conversation(const LinphoneAddress *la){ } }while(gtk_tree_model_iter_next(model,&iter)); } - } + } } void linphone_gtk_notebook_tab_select(GtkNotebook *notebook,GtkWidget *page,guint page_num, gpointer data){ @@ -595,11 +595,11 @@ static int get_friend_weight(const LinphoneFriend *lf){ int w=0; LinphoneCore *lc=linphone_gtk_get_core(); LinphoneChatRoom *cr=linphone_core_get_chat_room(lc,linphone_friend_get_address(lf)); - + if (cr && linphone_chat_room_get_unread_messages_count(cr)>0){ w+=2000; } - + switch(linphone_friend_get_status(lf)){ case LinphoneStatusOnline: w+=1000; @@ -685,7 +685,7 @@ static void linphone_gtk_friend_list_init(GtkWidget *friendlist){ gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(friendlist),friend_search_func,NULL,NULL); gtk_tree_view_set_search_column(GTK_TREE_VIEW(friendlist),FRIEND_NAME); gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store),FRIEND_NAME,friend_sort,NULL,NULL); - + /*Name and presence column*/ renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes (_("Presence status"), @@ -781,8 +781,9 @@ gboolean linphone_gtk_directory_search_focus_in(GtkWidget *entry){ void linphone_gtk_directory_search_activate(GtkWidget *entry){ LinphoneProxyConfig *cfg; + GtkWidget *w; linphone_core_get_default_proxy(linphone_gtk_get_core(),&cfg); - GtkWidget *w=linphone_gtk_show_buddy_lookup_window(linphone_proxy_config_get_sip_setup_context(cfg)); + w=linphone_gtk_show_buddy_lookup_window(linphone_proxy_config_get_sip_setup_context(cfg)); if (GPOINTER_TO_INT(g_object_get_data(G_OBJECT(entry),"active"))==1) linphone_gtk_buddy_lookup_set_keyword(w,gtk_entry_get_text(GTK_ENTRY(entry))); } @@ -809,7 +810,7 @@ void linphone_gtk_show_friends(void){ if (gtk_tree_view_get_model(GTK_TREE_VIEW(friendlist))==NULL){ linphone_gtk_friend_list_init(friendlist); } - + store=GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(friendlist))); gtk_list_store_clear(store); @@ -1076,7 +1077,7 @@ static gint tree_view_get_cell_from_pos(GtkTreeView *view, guint x, guint y){ gint colx = 0; GtkTreePath *path; GtkTreeViewDropPosition pos; - + g_return_val_if_fail ( view != NULL, 0 ); columns = gtk_tree_view_get_columns(view); @@ -1086,8 +1087,7 @@ static gint tree_view_get_cell_from_pos(GtkTreeView *view, guint x, guint y){ GtkTreeViewColumn *checkcol = (GtkTreeViewColumn*) node->data; if (x >= colx && x < (colx + checkcol->width)){ col = checkcol; - gint num = get_col_number_from_tree_view_column(col); - return num; + return get_col_number_from_tree_view_column(col); } else { colx += checkcol->width; } diff --git a/gtk/incall_view.c b/gtk/incall_view.c index a70fb468d..a9ef8e272 100644 --- a/gtk/incall_view.c +++ b/gtk/incall_view.c @@ -269,7 +269,7 @@ static void _refresh_call_stats(GtkWidget *callstats, LinphoneCall *call){ gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(callstats,"audio_bandwidth_usage")),tmp); g_free(tmp); if (has_video){ - gchar *size_r=g_strdup_printf(_("%ix%i @ %f fps"),size_received.width,size_received.height, + gchar *size_r=g_strdup_printf(_("%ix%i @ %f fps"),size_received.width,size_received.height, linphone_call_params_get_received_framerate(curparams)); gchar *size_s=g_strdup_printf(_("%ix%i @ %f fps"),size_sent.width,size_sent.height, linphone_call_params_get_sent_framerate(curparams)); @@ -366,6 +366,11 @@ void linphone_gtk_create_in_call_view(LinphoneCall *call){ GtkNotebook *notebook=(GtkNotebook *)linphone_gtk_get_widget(main_window,"viewswitch"); static int call_index=1; int idx; + GtkWidget *transfer; + GtkWidget *conf; + GtkWidget *button; + GtkWidget *image; + if (ms_list_size(linphone_core_get_calls(linphone_gtk_get_core()))==1){ /*this is the only call at this time */ @@ -386,19 +391,19 @@ void linphone_gtk_create_in_call_view(LinphoneCall *call){ linphone_gtk_enable_mute_button( GTK_BUTTON(linphone_gtk_get_widget(call_view,"incall_mute")),FALSE); - GtkWidget *transfer = linphone_gtk_get_widget(call_view,"transfer_button"); + transfer = linphone_gtk_get_widget(call_view,"transfer_button"); gtk_button_set_image(GTK_BUTTON(transfer),gtk_image_new_from_stock (GTK_STOCK_GO_FORWARD,GTK_ICON_SIZE_BUTTON)); g_signal_connect(G_OBJECT(transfer),"clicked",(GCallback)transfer_button_clicked,call); gtk_widget_hide(transfer); - GtkWidget *conf = linphone_gtk_get_widget(call_view,"conference_button"); + conf = linphone_gtk_get_widget(call_view,"conference_button"); gtk_button_set_image(GTK_BUTTON(conf),gtk_image_new_from_stock (GTK_STOCK_ADD,GTK_ICON_SIZE_BUTTON)); g_signal_connect(G_OBJECT(conf),"clicked",(GCallback)conference_button_clicked,call); gtk_widget_hide(conf); - GtkWidget *button=linphone_gtk_get_widget(call_view,"terminate_call"); - GtkWidget *image=create_pixmap("stopcall-small.png"); + button=linphone_gtk_get_widget(call_view,"terminate_call"); + image=create_pixmap("stopcall-small.png"); gtk_button_set_label(GTK_BUTTON(button),_("Hang up")); gtk_button_set_image(GTK_BUTTON(button),image); gtk_widget_show(image); @@ -418,6 +423,7 @@ static void video_button_clicked(GtkWidget *button, LinphoneCall *call){ void linphone_gtk_update_video_button(LinphoneCall *call){ GtkWidget *call_view=(GtkWidget*)linphone_call_get_user_pointer(call); GtkWidget *button; + GtkWidget *conf_frame; const LinphoneCallParams *params=linphone_call_get_current_params(call); gboolean has_video=linphone_call_params_video_enabled(params); if (call_view==NULL) return; @@ -434,7 +440,7 @@ void linphone_gtk_update_video_button(LinphoneCall *call){ g_signal_connect(G_OBJECT(button),"clicked",(GCallback)video_button_clicked,call); g_object_set_data(G_OBJECT(button),"signal_connected",GINT_TO_POINTER(1)); } - GtkWidget *conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(linphone_gtk_get_main_window()),"conf_frame"); + conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(linphone_gtk_get_main_window()),"conf_frame"); gtk_widget_set_sensitive(button,linphone_call_get_state(call)==LinphoneCallStreamsRunning); if(conf_frame!=NULL){ gtk_widget_set_sensitive(button,FALSE); @@ -753,10 +759,13 @@ static gboolean in_call_view_terminated(LinphoneCall *call){ void linphone_gtk_in_call_view_terminate(LinphoneCall *call, const char *error_msg){ GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call); + GtkWidget *status; + gboolean in_conf; + guint taskid; if(callview==NULL) return; - GtkWidget *status=linphone_gtk_get_widget(callview,"in_call_status"); - guint taskid=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(callview),"taskid")); - gboolean in_conf=linphone_call_params_get_local_conference_mode(linphone_call_get_current_params(call)); + status=linphone_gtk_get_widget(callview,"in_call_status"); + taskid=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(callview),"taskid")); + in_conf=linphone_call_params_get_local_conference_mode(linphone_call_get_current_params(call)); if (status==NULL) return; if (error_msg==NULL) @@ -896,8 +905,9 @@ void linphone_gtk_record_call_toggled(GtkWidget *button){ GtkWidget *callview; GtkWidget *label; if (call){ + const LinphoneCallParams *params; callview=(GtkWidget*)linphone_call_get_user_pointer (call); - const LinphoneCallParams *params=linphone_call_get_current_params(call); + params=linphone_call_get_current_params(call); filepath=linphone_call_params_get_record_file(params); label=linphone_gtk_get_widget(callview,"record_status"); }else if (is_conf){ diff --git a/gtk/main.c b/gtk/main.c index a08681dde..66cb27035 100644 --- a/gtk/main.c +++ b/gtk/main.c @@ -864,7 +864,7 @@ static gboolean launch_contact_provider_search(void *userdata) if( ldap && strlen(predicate) >= 3 ){ // don't search too small predicates unsigned int max_res_count = linphone_ldap_contact_provider_get_max_result(ldap); - + LinphoneContactSearch* search; if( previous_search && (strstr(predicate, previous_search) == predicate) && // last search contained results from this one (prev_res_count != max_res_count) ){ // and we didn't reach the max result limit @@ -879,7 +879,7 @@ static gboolean launch_contact_provider_search(void *userdata) gtk_object_set_data(GTK_OBJECT(uribar), "previous_search", ms_strdup(predicate)); ms_message("launch_contact_provider_search"); - LinphoneContactSearch* search =linphone_contact_provider_begin_search( + search =linphone_contact_provider_begin_search( linphone_contact_provider_cast(ldap_provider), predicate, on_contact_provider_search_results, uribar ); @@ -940,6 +940,7 @@ static void linphone_gtk_update_call_buttons(LinphoneCall *call){ //bool_t stop_active=FALSE; bool_t add_call=FALSE; int call_list_size=ms_list_size(calls); + GtkWidget *conf_frame; if (calls==NULL){ start_active=TRUE; @@ -962,7 +963,7 @@ static void linphone_gtk_update_call_buttons(LinphoneCall *call){ gtk_widget_set_visible(button,add_call); //gtk_widget_set_sensitive(linphone_gtk_get_widget(mw,"terminate_call"),stop_active); - GtkWidget *conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(mw),"conf_frame"); + conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(mw),"conf_frame"); if(conf_frame==NULL){ linphone_gtk_enable_transfer_button(lc,call_list_size>1); linphone_gtk_enable_conference_button(lc,call_list_size>1); @@ -1000,7 +1001,7 @@ gchar *linphone_gtk_get_record_path(const LinphoneAddress *address, gboolean is_ break; } } - + if (address){ id=linphone_address_get_username(address); if (id==NULL) id=linphone_address_get_domain(address); @@ -1172,13 +1173,14 @@ static void linphone_gtk_new_subscriber_response(GtkWidget *dialog, guint respon static void linphone_gtk_new_unknown_subscriber(LinphoneCore *lc, LinphoneFriend *lf, const char *url){ GtkWidget *dialog; + gchar *message; if (linphone_gtk_get_ui_config_int("subscribe_deny_all",0)){ linphone_core_reject_subscriber(linphone_gtk_get_core(),lf); return; } - gchar *message=g_strdup_printf(_("%s would like to add you to his contact list.\nWould you allow him to see your presence status or add him to your contact list ?\nIf you answer no, this person will be temporarily blacklisted."),url); + message=g_strdup_printf(_("%s would like to add you to his contact list.\nWould you allow him to see your presence status or add him to your contact list ?\nIf you answer no, this person will be temporarily blacklisted."),url); dialog = gtk_message_dialog_new ( GTK_WINDOW(linphone_gtk_get_main_window()), GTK_DIALOG_DESTROY_WITH_PARENT, @@ -1540,7 +1542,7 @@ static void update_registration_status(LinphoneProxyConfig *cfg, LinphoneRegistr }while(gtk_tree_model_iter_next(model,&iter)); } if (!found) { - g_warning("Could not find proxy config in combo box of identities."); + /*ignored, this is a notification for a removed proxy config.*/ return; } switch (rs){ @@ -2001,10 +2003,11 @@ void linphone_gtk_keypad_key_released(GtkWidget *w, GdkEvent *event, gpointer us void linphone_gtk_create_keypad(GtkWidget *button){ GtkWidget *mw=linphone_gtk_get_main_window(); GtkWidget *k=(GtkWidget *)g_object_get_data(G_OBJECT(mw),"keypad"); + GtkWidget *keypad; if(k!=NULL){ gtk_widget_destroy(k); } - GtkWidget *keypad=linphone_gtk_create_window("keypad"); + keypad=linphone_gtk_create_window("keypad"); linphone_gtk_connect_digits(keypad); linphone_gtk_init_dtmf_table(keypad); g_object_set_data(G_OBJECT(mw),"keypad",(gpointer)keypad); diff --git a/gtk/propertybox.c b/gtk/propertybox.c index 7ed960c46..677fe5f06 100644 --- a/gtk/propertybox.c +++ b/gtk/propertybox.c @@ -179,6 +179,7 @@ void linphone_gtk_ldap_save(GtkWidget *button) GtkEntry* entry; GtkToggleButton* toggle; GtkSpinButton* spin; + GtkComboBox* cbox; ms_message("SAVE LDAP"); @@ -204,7 +205,7 @@ void linphone_gtk_ldap_save(GtkWidget *button) linphone_dictionary_set_string(dict, "sasl_realm", gtk_entry_get_text(entry)); - GtkComboBox* cbox = GTK_COMBO_BOX(linphone_gtk_get_widget(ldap_widget,"ldap_auth_method")); + cbox = GTK_COMBO_BOX(linphone_gtk_get_widget(ldap_widget,"ldap_auth_method")); linphone_dictionary_set_string(dict, "auth_method", gtk_combo_box_get_active_text(cbox)); entry = GTK_ENTRY(linphone_gtk_get_widget(ldap_widget,"ldap_base_object")); @@ -245,10 +246,11 @@ void linphone_gtk_ldap_save(GtkWidget *button) } void linphone_gtk_fill_video_sizes(GtkWidget *combo){ - const MSVideoSizeDef *def=linphone_core_get_supported_video_sizes(linphone_gtk_get_core());; - int i,active=0; + int i; + int active=0; char vsize_def[256]; MSVideoSize cur=linphone_core_get_preferred_video_size(linphone_gtk_get_core()); + const MSVideoSizeDef *def=linphone_core_get_supported_video_sizes(linphone_gtk_get_core());; /* glade creates a combo box without list model and text renderer, unless we fill it with a dummy text. This dummy text needs to be removed first*/ @@ -828,8 +830,11 @@ void linphone_gtk_show_sip_accounts(GtkWidget *w){ static void linphone_gtk_proxy_closed(GtkWidget *w){ LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)g_object_get_data(G_OBJECT(w),"config"); + gboolean was_editing=! GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"is_new")); if (cfg){ - linphone_proxy_config_done(cfg); + if (was_editing){ + linphone_proxy_config_done(cfg); + }else linphone_proxy_config_destroy(cfg); } } @@ -907,7 +912,15 @@ void linphone_gtk_proxy_address_changed(GtkEditable *editable){ void linphone_gtk_show_proxy_config(GtkWidget *pb, LinphoneProxyConfig *cfg){ GtkWidget *w=linphone_gtk_create_window("sip_account"); const char *tmp; - if (cfg){ + gboolean is_new=FALSE; + + if (!cfg) { + cfg=linphone_core_create_proxy_config(linphone_gtk_get_core()); + is_new=TRUE; + g_object_set_data(G_OBJECT(w),"is_new",GINT_TO_POINTER(TRUE)); + } + + if (!is_new){ linphone_proxy_config_edit(cfg); gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(w,"identity")), linphone_proxy_config_get_identity(cfg)); @@ -916,17 +929,19 @@ void linphone_gtk_show_proxy_config(GtkWidget *pb, LinphoneProxyConfig *cfg){ if (tmp) gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(w,"route")),tmp); tmp=linphone_proxy_config_get_contact_parameters(cfg); if (tmp) gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(w,"params")),tmp); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(w,"regperiod")), - linphone_proxy_config_get_expires(cfg)); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"register")), - linphone_proxy_config_register_enabled(cfg)); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"publish")), - linphone_proxy_config_publish_enabled(cfg)); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"avpf")), - linphone_proxy_config_avpf_enabled(cfg)); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(w,"avpf_rr_interval")), - linphone_proxy_config_get_avpf_rr_interval(cfg)); } + + gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(w,"regperiod")), + linphone_proxy_config_get_expires(cfg)); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"register")), + linphone_proxy_config_register_enabled(cfg)); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"publish")), + linphone_proxy_config_publish_enabled(cfg)); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"avpf")), + linphone_proxy_config_avpf_enabled(cfg)); + gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(w,"avpf_rr_interval")), + linphone_proxy_config_get_avpf_rr_interval(cfg)); + g_object_set_data(G_OBJECT(w),"config",(gpointer)cfg); g_object_set_data(G_OBJECT(w),"parameters",(gpointer)pb); g_object_weak_ref(G_OBJECT(w),(GWeakNotify)linphone_gtk_proxy_closed,w); @@ -944,12 +959,8 @@ void linphone_gtk_proxy_ok(GtkButton *button){ LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)g_object_get_data(G_OBJECT(w),"config"); int index=gtk_combo_box_get_active(GTK_COMBO_BOX(linphone_gtk_get_widget(w,"transport"))); LinphoneTransportType tport=(LinphoneTransportType)index; - gboolean was_editing=TRUE; + gboolean was_editing=! GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"is_new")); - if (!cfg){ - was_editing=FALSE; - cfg=linphone_proxy_config_new(); - } linphone_proxy_config_set_identity(cfg, gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(w,"identity")))); if (linphone_proxy_config_set_server_addr(cfg, @@ -1098,14 +1109,14 @@ static void linphone_gtk_fill_langs(GtkWidget *pb){ const char *all_langs="C " LINPHONE_ALL_LANGS; const char *name; int i=0,index=0; + int cur_lang_index=-1; + char text[256]={0}; const char *cur_lang; #if defined(WIN32) || defined(__APPLE__) cur_lang=getenv("LANG"); #else cur_lang=getenv("LANGUAGE"); #endif - int cur_lang_index=-1; - char text[256]={0}; if (cur_lang==NULL) cur_lang="C"; /* glade creates a combo box without list model and text renderer, unless we fill it with a dummy text. @@ -1581,7 +1592,7 @@ void linphone_gtk_edit_tunnel(GtkButton *button){ if (port==0) port=443; gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(w,"port")), port); - if (linphone_tunnel_enabled(tunnel)){ + if (linphone_tunnel_get_mode(tunnel)){ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"radio_enable")),1); } else{ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"radio_disable")),1); @@ -1625,7 +1636,7 @@ void linphone_gtk_tunnel_ok(GtkButton *button){ linphone_tunnel_config_set_host(config, host); linphone_tunnel_config_set_port(config, port); linphone_tunnel_add_server(tunnel, config); - linphone_tunnel_enable(tunnel,enabled); + linphone_tunnel_set_mode(tunnel, (enabled ? LinphoneTunnelModeEnable : LinphoneTunnelModeDisable)); linphone_tunnel_set_http_proxy(tunnel,http_host,http_port,username,password); gtk_widget_destroy(w); diff --git a/gtk/setupwizard.c b/gtk/setupwizard.c index 27f7363b7..491014625 100644 --- a/gtk/setupwizard.c +++ b/gtk/setupwizard.c @@ -44,7 +44,7 @@ static GtkWidget *create_setup_signin_choice(){ GtkWidget *t2=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(t1),_("I have already a linphone.org account and I just want to use it")); GtkWidget *t3=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(t1),_("I have already a sip account and I just want to use it")); GtkWidget *t4=gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(t1),_("I want to specify a remote configuration URI")); - + gtk_box_pack_start (GTK_BOX (vbox), t1, TRUE, TRUE, 2); gtk_box_pack_start (GTK_BOX (vbox), t2, TRUE, TRUE, 2); gtk_box_pack_start (GTK_BOX (vbox), t3, TRUE, TRUE, 2); @@ -89,14 +89,20 @@ static GtkWidget *create_linphone_account_informations_page() { GtkWidget *label=gtk_label_new(_("Enter your linphone.org username")); GdkColor color; + GtkWidget *labelEmpty; + GtkWidget *labelUsername; + GtkWidget *entryUsername; + GtkWidget *labelPassword; + GtkWidget *entryPassword; + gdk_color_parse ("red", &color); - GtkWidget *labelEmpty=gtk_label_new(NULL); + labelEmpty=gtk_label_new(NULL); gtk_widget_modify_fg(labelEmpty, GTK_STATE_NORMAL, &color); - GtkWidget *labelUsername=gtk_label_new(_("Username:")); - GtkWidget *entryUsername=gtk_entry_new(); - GtkWidget *labelPassword=gtk_label_new(_("Password:")); - GtkWidget *entryPassword=gtk_entry_new(); + labelUsername=gtk_label_new(_("Username:")); + entryUsername=gtk_entry_new(); + labelPassword=gtk_label_new(_("Password:")); + entryPassword=gtk_entry_new(); gtk_entry_set_visibility(GTK_ENTRY(entryPassword), FALSE); gtk_table_attach_defaults(GTK_TABLE(vbox), label, 0, 2, 0, 1); @@ -118,19 +124,28 @@ static GtkWidget *create_account_informations_page() { GtkWidget *label=gtk_label_new(_("Enter your account informations")); GdkColor color; + GtkWidget *labelEmpty; + GtkWidget *labelUsername; + GtkWidget *labelPassword; + GtkWidget *entryPassword; + GtkWidget *labelDomain; + GtkWidget *labelProxy; + GtkWidget *entryUsername; + GtkWidget *entryDomain; + GtkWidget *entryRoute; gdk_color_parse ("red", &color); - GtkWidget *labelEmpty=gtk_label_new(NULL); + labelEmpty=gtk_label_new(NULL); gtk_widget_modify_fg(labelEmpty, GTK_STATE_NORMAL, &color); - GtkWidget *labelUsername=gtk_label_new(_("Username*")); - GtkWidget *labelPassword=gtk_label_new(_("Password*")); - GtkWidget *entryPassword=gtk_entry_new(); + labelUsername=gtk_label_new(_("Username*")); + labelPassword=gtk_label_new(_("Password*")); + entryPassword=gtk_entry_new(); gtk_entry_set_visibility(GTK_ENTRY(entryPassword), FALSE); - GtkWidget *labelDomain=gtk_label_new(_("Domain*")); - GtkWidget *labelProxy=gtk_label_new(_("Proxy")); - GtkWidget *entryUsername=gtk_entry_new(); - GtkWidget *entryDomain=gtk_entry_new(); - GtkWidget *entryRoute=gtk_entry_new(); + labelDomain=gtk_label_new(_("Domain*")); + labelProxy=gtk_label_new(_("Proxy")); + entryUsername=gtk_entry_new(); + entryDomain=gtk_entry_new(); + entryRoute=gtk_entry_new(); gtk_table_attach_defaults(GTK_TABLE(vbox), label, 0, 2, 0, 1); gtk_table_attach_defaults(GTK_TABLE(vbox), labelUsername, 0, 1, 1, 2); @@ -309,19 +324,25 @@ static GtkWidget *create_account_information_page() { GtkWidget *labelPassword2=gtk_label_new(_("Confirm your password: (*)")); GtkWidget *entryUsername=gtk_entry_new(); GtkWidget *entryPassword=gtk_entry_new(); - gtk_entry_set_visibility(GTK_ENTRY(entryPassword), FALSE); - GtkWidget *entryEmail=gtk_entry_new(); - GtkWidget *entryPassword2=gtk_entry_new(); - gtk_entry_set_visibility(GTK_ENTRY(entryPassword2), FALSE); - GtkWidget *checkNewsletter=gtk_check_button_new_with_label("Keep me informed with linphone updates"); - + GtkWidget *entryEmail; + GtkWidget *entryPassword2; + GtkWidget *checkNewsletter; + GtkWidget *labelError; + GtkWidget *passwordVbox1; + GtkWidget *passwordVbox2; GdkColor color; + gtk_entry_set_visibility(GTK_ENTRY(entryPassword), FALSE); + entryEmail=gtk_entry_new(); + entryPassword2=gtk_entry_new(); + gtk_entry_set_visibility(GTK_ENTRY(entryPassword2), FALSE); + checkNewsletter=gtk_check_button_new_with_label(_("Keep me informed with linphone updates")); + gdk_color_parse ("red", &color); - GtkWidget *labelError=gtk_label_new(NULL); + labelError=gtk_label_new(NULL); gtk_widget_modify_fg(labelError, GTK_STATE_NORMAL, &color); - GtkWidget *passwordVbox1=gtk_vbox_new(FALSE,2); - GtkWidget *passwordVbox2=gtk_vbox_new(FALSE,2); + passwordVbox1=gtk_vbox_new(FALSE,2); + passwordVbox2=gtk_vbox_new(FALSE,2); gtk_box_pack_start (GTK_BOX (passwordVbox1), labelPassword, TRUE, FALSE, 2); gtk_box_pack_start (GTK_BOX (passwordVbox1), labelPassword2, TRUE, FALSE, 2); gtk_box_pack_start (GTK_BOX (passwordVbox2), entryPassword, TRUE, FALSE, 2); @@ -414,6 +435,8 @@ static void linphone_gtk_assistant_prepare(GtkWidget *assistant, GtkWidget *page if (pagenum == 5) { gtk_assistant_commit(GTK_ASSISTANT(assistant)); } else if (pagenum == gtk_assistant_get_n_pages(GTK_ASSISTANT(assistant)) - 1) { + LinphoneAddress *identity; + LinphoneAuthInfo *info; // Saving the account and making it default LinphoneAccountCreator *creator=linphone_gtk_assistant_get_creator(assistant); LinphoneProxyConfig *cfg=linphone_proxy_config_new(); @@ -424,30 +447,33 @@ static void linphone_gtk_assistant_prepare(GtkWidget *assistant, GtkWidget *page linphone_proxy_config_enable_publish(cfg, FALSE); linphone_proxy_config_enable_register(cfg, TRUE); - LinphoneAddress *identity = linphone_address_new(creator->username); - LinphoneAuthInfo *info=linphone_auth_info_new(linphone_address_get_username(identity), NULL, creator->password, NULL, NULL, linphone_address_get_domain(identity)); + identity = linphone_address_new(creator->username); + info=linphone_auth_info_new(linphone_address_get_username(identity), NULL, creator->password, NULL, NULL, linphone_address_get_domain(identity)); linphone_core_add_auth_info(linphone_gtk_get_core(),info); linphone_address_destroy(identity); - - // If account created on sip.linphone.org, we configure linphone to use TLS by default - if (strcmp(creator->domain, "sip:sip.linphone.org") == 0 && linphone_core_sip_transport_supported(linphone_gtk_get_core(),LinphoneTransportTls)) { - LinphoneAddress *addr=linphone_address_new(creator->domain); - char *tmp; - linphone_address_set_transport(addr, LinphoneTransportTls); - tmp=linphone_address_as_string(addr); - linphone_proxy_config_set_server_addr(cfg,tmp); - linphone_proxy_config_set_route(cfg,tmp); - ms_free(tmp); - linphone_address_destroy(addr); + + if (strcmp(creator->domain, "sip:sip.linphone.org") == 0 ){ + linphone_proxy_config_enable_avpf(cfg,TRUE); + // If account created on sip.linphone.org, we configure linphone to use TLS by default + if (linphone_core_sip_transport_supported(linphone_gtk_get_core(),LinphoneTransportTls)) { + LinphoneAddress *addr=linphone_address_new(creator->domain); + char *tmp; + linphone_address_set_transport(addr, LinphoneTransportTls); + tmp=linphone_address_as_string(addr); + linphone_proxy_config_set_server_addr(cfg,tmp); + linphone_proxy_config_set_route(cfg,tmp); + ms_free(tmp); + linphone_address_destroy(addr); + } } - + if (linphone_core_add_proxy_config(linphone_gtk_get_core(),cfg)==-1) return; linphone_core_set_default_proxy(linphone_gtk_get_core(),cfg); linphone_gtk_load_identities(); - + } } @@ -486,9 +512,9 @@ static int linphone_gtk_assistant_forward(int curpage, gpointer data){ else if (curpage == 2) { // Account's informations entered LinphoneAccountCreator *c=linphone_gtk_assistant_get_creator(w); gchar identity[128]; + gchar proxy[128]; g_snprintf(identity, sizeof(identity), "sip:%s@%s", gtk_entry_get_text(GTK_ENTRY(g_object_get_data(G_OBJECT(box),"username"))), gtk_entry_get_text(GTK_ENTRY(g_object_get_data(G_OBJECT(box),"domain")))); - gchar proxy[128]; g_snprintf(proxy, sizeof(proxy), "sip:%s", gtk_entry_get_text(GTK_ENTRY(g_object_get_data(G_OBJECT(box),"domain")))); linphone_account_creator_set_username(c, identity); @@ -557,25 +583,35 @@ void linphone_gtk_close_assistant(void){ } void linphone_gtk_show_assistant(void){ + GtkWidget *w; + GtkWidget *p1; + GtkWidget *p2; + GtkWidget *p31; + GtkWidget *p32; + GtkWidget *p33; + //GtkWidget *confirm; + GtkWidget *validate; + GtkWidget *error; + GtkWidget *end; if(the_assistant!=NULL) return; - GtkWidget *w=the_assistant=gtk_assistant_new(); + w=the_assistant=gtk_assistant_new(); gtk_window_set_resizable (GTK_WINDOW(w), FALSE); gtk_window_set_title(GTK_WINDOW(w),_("SIP account configuration assistant")); ok = create_pixbuf(linphone_gtk_get_ui_config("ok","ok.png")); notok = create_pixbuf(linphone_gtk_get_ui_config("notok","notok.png")); - GtkWidget *p1=create_intro(); - GtkWidget *p2=create_setup_signin_choice(); - GtkWidget *p31=create_account_informations_page(); - GtkWidget *p32=create_linphone_account_informations_page(); - GtkWidget *p33=create_account_information_page(); - //GtkWidget *confirm=create_confirmation_page(); - GtkWidget *validate=wait_for_activation(); - GtkWidget *error=create_error_page(); - GtkWidget *end=create_finish_page(); - + p1=create_intro(); + p2=create_setup_signin_choice(); + p31=create_account_informations_page(); + p32=create_linphone_account_informations_page(); + p33=create_account_information_page(); + //confirm=create_confirmation_page(); + validate=wait_for_activation(); + error=create_error_page(); + end=create_finish_page(); + linphone_gtk_assistant_init(w); gtk_assistant_append_page(GTK_ASSISTANT(w),p1); gtk_assistant_set_page_type(GTK_ASSISTANT(w),p1,GTK_ASSISTANT_PAGE_INTRO); diff --git a/gtk/singleinstance.c b/gtk/singleinstance.c index e78f6ac6a..591d5d7cd 100644 --- a/gtk/singleinstance.c +++ b/gtk/singleinstance.c @@ -58,7 +58,7 @@ static gboolean execute_wakeup(char *buf){ static void * server_pipe_thread(void *pointer){ ortp_pipe_t child; - + do{ child=ortp_server_pipe_accept_client(server_pipe); if (server_pipe_running && child!=(ortp_pipe_t)-1){ @@ -87,8 +87,9 @@ static void linphone_gtk_init_pipe(const char *name){ } bool_t linphone_gtk_init_instance(const char *app_name, int option, const char *addr_to_call){ + ortp_pipe_t p; pipe_name=make_name(app_name); - ortp_pipe_t p=ortp_client_pipe_connect(pipe_name); + p=ortp_client_pipe_connect(pipe_name); if (p!=(ortp_pipe_t)-1){ uint8_t buf[256]={0}; g_message("There is already a running instance."); diff --git a/gtk/support.c b/gtk/support.c index 81754bb45..615ac6562 100644 --- a/gtk/support.c +++ b/gtk/support.c @@ -92,17 +92,17 @@ create_pixbuf_animation(const gchar *filename) gchar *pathname = NULL; GdkPixbufAnimation *pixbuf; GError *error = NULL; - + if (!filename || !filename[0]) return NULL; - + pathname = find_pixmap_file (filename); - + if (!pathname){ g_warning (_("Couldn't find pixmap file: %s"), filename); return NULL; } - + pixbuf = gdk_pixbuf_animation_new_from_file (pathname, &error); if (!pixbuf){ fprintf (stderr, "Failed to load pixbuf file: %s: %s\n", @@ -156,6 +156,11 @@ const char *linphone_gtk_get_lang(const char *config_file){ void linphone_gtk_set_lang(const char *code){ LpConfig *cfg=linphone_core_get_config(linphone_gtk_get_core()); const char *curlang; + + #ifdef WIN32 + char tmp[128]; + #endif + #if defined(WIN32) || defined(__APPLE__) curlang=getenv("LANG"); #else @@ -167,12 +172,11 @@ void linphone_gtk_set_lang(const char *code){ } lp_config_set_string(cfg,"GtkUi","lang",code); #ifdef WIN32 - char tmp[128]; snprintf(tmp,sizeof(tmp),"LANG=%s",code); _putenv(tmp); #elif __APPLE__ setenv("LANG",code,1); -#else +#else setenv("LANGUAGE",code,1); #endif } diff --git a/include/sal/sal.h b/include/sal/sal.h index 22feb58d3..f15349151 100644 --- a/include/sal/sal.h +++ b/include/sal/sal.h @@ -72,7 +72,9 @@ typedef enum { #define SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED 0x01 #define SAL_MEDIA_DESCRIPTION_CODEC_CHANGED 0x02 #define SAL_MEDIA_DESCRIPTION_CRYPTO_CHANGED 0x04 -#define SAL_MEDIA_DESCRIPTION_CHANGED (SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED | SAL_MEDIA_DESCRIPTION_CODEC_CHANGED | SAL_MEDIA_DESCRIPTION_CRYPTO_CHANGED) +#define SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED 0x08 +#define SAL_MEDIA_DESCRIPTION_CHANGED (SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED | SAL_MEDIA_DESCRIPTION_CODEC_CHANGED |\ + SAL_MEDIA_DESCRIPTION_CRYPTO_CHANGED |SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED) const char* sal_transport_to_string(SalTransport transport); SalTransport sal_transport_parse(const char*); @@ -285,6 +287,7 @@ typedef struct SalOpBase{ SalMediaDescription *remote_media; void *user_pointer; const char* call_id; + char* realm; SalAddress* service_route; /*as defined by rfc3608, might be a list*/ SalCustomHeader *sent_custom_headers; SalCustomHeader *recv_custom_headers; @@ -412,7 +415,7 @@ typedef void (*SalOnCallReceived)(SalOp *op); typedef void (*SalOnCallRinging)(SalOp *op); typedef void (*SalOnCallAccepted)(SalOp *op); typedef void (*SalOnCallAck)(SalOp *op); -typedef void (*SalOnCallUpdating)(SalOp *op);/*< Called when a reINVITE/UPDATE is received*/ +typedef void (*SalOnCallUpdating)(SalOp *op, bool_t is_update);/*< Called when a reINVITE/UPDATE is received*/ typedef void (*SalOnCallTerminated)(SalOp *op, const char *from); typedef void (*SalOnCallFailure)(SalOp *op); typedef void (*SalOnCallReleased)(SalOp *salop); @@ -516,6 +519,10 @@ int sal_get_listening_port(Sal *ctx, SalTransport tr); int sal_unlisten_ports(Sal *ctx); int sal_transport_available(Sal *ctx, SalTransport t); void sal_set_dscp(Sal *ctx, int dscp); +void sal_set_supported_tags(Sal *ctx, const char* tags); +void sal_add_supported_tag(Sal *ctx, const char* tag); +void sal_remove_supported_tag(Sal *ctx, const char* tag); +const char *sal_get_supported_tags(Sal *ctx); int sal_reset_transports(Sal *ctx); ortp_socket_t sal_get_socket(Sal *ctx); void sal_set_user_agent(Sal *ctx, const char *user_agent); @@ -560,6 +567,7 @@ void sal_op_set_contact_address(SalOp *op, const SalAddress* address); void sal_op_set_route(SalOp *op, const char *route); void sal_op_set_route_address(SalOp *op, const SalAddress* address); void sal_op_add_route_address(SalOp *op, const SalAddress* address); +void sal_op_set_realm(SalOp *op, const char *realm); void sal_op_set_from(SalOp *op, const char *from); void sal_op_set_from_address(SalOp *op, const SalAddress *from); void sal_op_set_to(SalOp *op, const char *to); @@ -613,7 +621,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_update(SalOp *h, const char *subject); +int sal_call_update(SalOp *h, const char *subject, bool_t no_user_consent); SalMediaDescription * sal_call_get_remote_media_description(SalOp *h); SalMediaDescription * sal_call_get_final_media_description(SalOp *h); int sal_call_refer(SalOp *h, const char *refer_to); @@ -749,5 +757,5 @@ int sal_body_has_type(const SalBody *body, const char *type, const char *subtype int sal_lines_get_value(const char *data, const char *key, char *value, size_t value_size); belle_sip_stack_t *sal_get_belle_sip_stack(Sal *sal); - +char* sal_op_get_public_uri(SalOp *sal); #endif diff --git a/java/common/org/linphone/core/LinphoneCall.java b/java/common/org/linphone/core/LinphoneCall.java index 90fe60ded..d75f1bbdb 100644 --- a/java/common/org/linphone/core/LinphoneCall.java +++ b/java/common/org/linphone/core/LinphoneCall.java @@ -323,4 +323,14 @@ public interface LinphoneCall { */ ErrorInfo getErrorInfo(); + /** + * attached a user data to a call + **/ + void setUserData(Object obj); + + /** + * Returns user data from a call. return null if any + * @return an Object. + */ + Object getUserData(); } diff --git a/java/common/org/linphone/core/LinphoneCallParams.java b/java/common/org/linphone/core/LinphoneCallParams.java index b226077cd..7086a56fb 100644 --- a/java/common/org/linphone/core/LinphoneCallParams.java +++ b/java/common/org/linphone/core/LinphoneCallParams.java @@ -76,6 +76,9 @@ public interface LinphoneCallParams { /** * Set a path to file where the call will be recorded. * Actual start of the recording is controlled by LinphoneCall.startRecording(). + * @param path Path to the file where the call will be recorded. If it is a WAV + * file, only audio will be written whereas if it is a MKV file, audio and video + * will be written. **/ void setRecordFile(String path); diff --git a/java/common/org/linphone/core/LinphoneChatMessage.java b/java/common/org/linphone/core/LinphoneChatMessage.java index d51a19251..930a064db 100644 --- a/java/common/org/linphone/core/LinphoneChatMessage.java +++ b/java/common/org/linphone/core/LinphoneChatMessage.java @@ -14,21 +14,25 @@ public interface LinphoneChatMessage { private final String mStringValue; /** - * Idle + * Initial state */ public final static State Idle = new State(0,"Idle"); /** - * Incoming call received. + * Delivery in progress */ public final static State InProgress = new State(1,"InProgress"); /** - * Outgoing call initialiazed. + * Message succesffully delivered an acknoleged by remote end point */ public final static State Delivered = new State(2,"Delivered"); /** - * Outgoing call in progress. + * Message was not delivered */ public final static State NotDelivered = new State(3,"NotDelivered"); + /** + * Message was received(and acknowledged) but cannot get file from server + */ + public final static State FileTransferError = new State(4,"FileTransferError"); private State(int value,String stringValue) { mValue = value; @@ -74,6 +78,12 @@ public interface LinphoneChatMessage { */ LinphoneAddress getFrom(); + /** + * Get destination address of the LinphoneChatMessage. + * @return the LinphoneAddress in the To field of the message. + */ + LinphoneAddress getTo(); + /** * Linphone message can carry external body as defined by rfc2017 * @param message #LinphoneChatMessage @@ -147,4 +157,26 @@ public interface LinphoneChatMessage { * @return an ErrorInfo. */ ErrorInfo getErrorInfo(); + + /** + * Start the download of the file bundled in the message + */ + void startFileDownload(LinphoneChatMessage.StateListener listener); + + /** + * Get the file_transfer_information (used by call backs to recover informations during a rcs file transfer) + * @return a pointer to the LinphoneContent structure or NULL if not present. + */ + LinphoneContent getFileTransferInformation(); + + /** + * Sets data in the chat message + * @param data to store in the message + */ + void setAppData(String data); + + /** + * @return the data stored in the chat message if any, else null + */ + String getAppData(); } diff --git a/java/common/org/linphone/core/LinphoneChatRoom.java b/java/common/org/linphone/core/LinphoneChatRoom.java index c1e635c0a..1f8c58f8c 100644 --- a/java/common/org/linphone/core/LinphoneChatRoom.java +++ b/java/common/org/linphone/core/LinphoneChatRoom.java @@ -21,8 +21,8 @@ package org.linphone.core; import org.linphone.core.LinphoneChatMessage.State; /** - * - * A chat room is the place where text messages are exchanged. + * + * A chat room is the place where text messages are exchanged. Can be created by linphone_core_create_chat_room(). * */ @@ -33,17 +33,19 @@ public interface LinphoneChatRoom { * @return LinphoneAddress peer address */ LinphoneAddress getPeerAddress(); + /** * send a message to peer member of this chat room. * @param message to be sent */ void sendMessage(String message); + /** * Send a message to peer member of this chat room. * @param chat message */ void sendMessage(LinphoneChatMessage message, LinphoneChatMessage.StateListener listener); - + /** * Create a LinphoneChatMessage * @param chatRoom chat room associated to the message @@ -51,31 +53,45 @@ public interface LinphoneChatRoom { * @return LinphoneChatMessage object */ LinphoneChatMessage createLinphoneChatMessage(String message); - + /** * Returns the chat history associated with the peer address associated with this chat room * @return an array of LinphoneChatMessage */ LinphoneChatMessage[] getHistory(); - + /** * Returns the chat history associated with the peer address associated with this chat room * @param limit the maximum number of messages to fetch * @return an array of LinphoneChatMessage */ LinphoneChatMessage[] getHistory(int limit); - + + /** + * Returns the chat history associated with the peer address associated with this chat room for the given range, sorted from oldest to most recent + * @param begin the first (most recent) message to retrieve. Newest message has index 0. If negative, use value 0 instead. + * @param end the last (oldest) message to retrieve. Oldest message has value "history size" - 1 (equivalent to -1). If negative or lower than begin value, value is given, use -1. + * @return an array of LinphoneChatMessage, empty if nothing has been found + */ + LinphoneChatMessage[] getHistoryRange(int begin, int end); + /** * Destroys a LinphoneChatRoom. */ void destroy(); - + /** * Returns the amount of unread messages associated with the peer of this chatRoom. * @return the amount of unread messages */ int getUnreadMessagesCount(); - + + /** + * Returns the amount of messages associated with the peer of this chatRoom. + * @return the amount of messages in the conversation + */ + int getHistorySize(); + /** * Deletes all the messages associated with the peer of this chat room */ @@ -91,32 +107,46 @@ public interface LinphoneChatRoom { * @return true if the remote is currently composing a message, false otherwise. */ boolean isRemoteComposing(); - + /** * Marks all the messages in this conversation as read */ void markAsRead(); - + /** * Deletes a message * @param message the message to delete */ void deleteMessage(LinphoneChatMessage message); - + /** * Update the value stored in the database for the external_body_url field * @param message to update */ void updateUrl(LinphoneChatMessage message); - + /** * Create a LinphoneChatMessage * @return LinphoneChatMessage object */ LinphoneChatMessage createLinphoneChatMessage(String message, String url, State state, long timestamp, boolean isRead, boolean isIncoming); + /** * Returns a back pointer to the core managing the chat room. * @return the LinphoneCore */ LinphoneCore getCore(); + + /** + * Create a message attached to a dedicated chat room with a particular content. + * @param content LinphoneContent initial content. + * @return a new LinphoneChatMessage + */ + LinphoneChatMessage createFileTransferMessage(LinphoneContent content); + + /** + * Cancel an ongoing file transfer attached to this message (upload or download) + * @param message + */ + void cancelFileTransfer(LinphoneChatMessage message); } diff --git a/java/common/org/linphone/core/LinphoneContent.java b/java/common/org/linphone/core/LinphoneContent.java index 10c6e3dc9..eb41c62f7 100644 --- a/java/common/org/linphone/core/LinphoneContent.java +++ b/java/common/org/linphone/core/LinphoneContent.java @@ -31,10 +31,21 @@ public interface LinphoneContent { **/ byte [] getData(); /** - * Get the data size. - * @return the data size. + * Get the expected data size. + * @return the expected data size */ - int getSize(); + int getExpectedSize(); + + /** + * Sets the expected data size + */ + void setExpectedSize(int size); + + /** + * Return the size of the data field + * @return the size of the data field + */ + int getRealSize(); /** * Set the content type, for example "application" @@ -59,4 +70,8 @@ public interface LinphoneContent { * Set the data, as a byte buffer. **/ void setData(byte data[]); + + void setName(String name); + + String getName(); } diff --git a/java/common/org/linphone/core/LinphoneCore.java b/java/common/org/linphone/core/LinphoneCore.java index 332a85be0..3a9e1d86d 100644 --- a/java/common/org/linphone/core/LinphoneCore.java +++ b/java/common/org/linphone/core/LinphoneCore.java @@ -26,7 +26,7 @@ import org.linphone.mediastream.video.capture.hwconf.AndroidCameraConfiguration; import android.view.SurfaceView; /** - * Linphone core main object created by method {@link LinphoneCoreFactory#createLinphoneCore(LinphoneCoreListener, String, String, Object)}. + * Linphone core main object created by method {@link LinphoneCoreFactory#createLinphoneCore(LinphoneCoreListener, String, String, Object)}. * */ @@ -35,12 +35,12 @@ public interface LinphoneCore { * linphone core states */ static public class GlobalState { - + static private Vector values = new Vector(); /** * Off */ - static public GlobalState GlobalOff = new GlobalState(0,"GlobalOff"); + static public GlobalState GlobalOff = new GlobalState(0,"GlobalOff"); /** * Startup */ @@ -61,7 +61,7 @@ public interface LinphoneCore { private final int mValue; private final String mStringValue; - + private GlobalState(int value,String stringValue) { mValue = value; values.addElement(this); @@ -83,12 +83,12 @@ public interface LinphoneCore { * linphone remote provisioning states */ static public class RemoteProvisioningState { - + static private Vector values = new Vector(); /** * Off */ - static public RemoteProvisioningState ConfiguringSuccessful = new RemoteProvisioningState(0,"ConfiguringSuccessful"); + static public RemoteProvisioningState ConfiguringSuccessful = new RemoteProvisioningState(0,"ConfiguringSuccessful"); /** * Startup */ @@ -101,7 +101,7 @@ public interface LinphoneCore { private final int mValue; private final String mStringValue; - + private RemoteProvisioningState(int value,String stringValue) { mValue = value; values.addElement(this); @@ -124,12 +124,12 @@ public interface LinphoneCore { * */ static public class RegistrationState { - + private static Vector values = new Vector(); /** * None */ - public static RegistrationState RegistrationNone = new RegistrationState(0,"RegistrationNone"); + public static RegistrationState RegistrationNone = new RegistrationState(0,"RegistrationNone"); /** * In Progress */ @@ -149,7 +149,7 @@ public interface LinphoneCore { private final int mValue; private final String mStringValue; - + private RegistrationState(int value,String stringValue) { mValue = value; values.addElement(this); @@ -172,12 +172,12 @@ public interface LinphoneCore { * */ static public class FirewallPolicy { - + static private Vector values = new Vector(); /** * No firewall is assumed. */ - static public FirewallPolicy NoFirewall = new FirewallPolicy(0,"NoFirewall"); + static public FirewallPolicy NoFirewall = new FirewallPolicy(0,"NoFirewall"); /** * Use NAT address (discouraged) */ @@ -194,11 +194,11 @@ public interface LinphoneCore { * Use uPnP. */ static public FirewallPolicy UseUpnp = new FirewallPolicy(4,"UseUpnp"); - + private final int mValue; private final String mStringValue; - + private FirewallPolicy(int value,String stringValue) { mValue = value; values.addElement(this); @@ -219,7 +219,7 @@ public interface LinphoneCore { return mValue; } } - + /** * Linphone core SIP transport ports. * Use with {@link LinphoneCore#setSignalingTransportPorts(Transports)} @@ -238,7 +238,7 @@ public interface LinphoneCore { * tls port to listening on, negative value if not set * */ public int tls; - + public Transports() {}; public Transports(Transports t) { this.udp = t.udp; @@ -254,12 +254,12 @@ public interface LinphoneCore { * */ static public final class MediaEncryption { - + static private Vector values = new Vector(); /** * None */ - static public final MediaEncryption None = new MediaEncryption(0,"None"); + static public final MediaEncryption None = new MediaEncryption(0,"None"); /** * SRTP */ @@ -271,7 +271,7 @@ public interface LinphoneCore { protected final int mValue; private final String mStringValue; - + private MediaEncryption(int value,String stringValue) { mValue = value; values.addElement(this); @@ -289,11 +289,43 @@ public interface LinphoneCore { return mStringValue; } } + static public final class AdaptiveRateAlgorithm { + + static private Vector values = new Vector(); + /** + * Simple + */ + static public final AdaptiveRateAlgorithm Simple = new AdaptiveRateAlgorithm(0,"Simple"); + /** + * Stateful + */ + static public final AdaptiveRateAlgorithm Stateful = new AdaptiveRateAlgorithm(1,"Stateful"); + protected final int mValue; + private final String mStringValue; + + + private AdaptiveRateAlgorithm(int value,String stringValue) { + mValue = value; + values.addElement(this); + mStringValue=stringValue; + } + public static AdaptiveRateAlgorithm fromString(String value) { + + for (int i=0; i values = new Vector(); /* Do not change the values of these constants or the strings associated with them to prevent breaking the collection of echo canceller calibration results during the wizard! */ @@ -321,7 +353,7 @@ public interface LinphoneCore { private final int mValue; private final String mStringValue; - + private EcCalibratorStatus(int value,String stringValue) { mValue = value; values.addElement(this); @@ -342,11 +374,11 @@ public interface LinphoneCore { return mValue; } } - + static public class UpnpState { static private Vector values = new Vector(); /** - * Idle + * Idle */ static public UpnpState Idle = new UpnpState(0, "Idle"); /** @@ -370,11 +402,11 @@ public interface LinphoneCore { */ static public UpnpState Ok = new UpnpState(5, "Ok"); /** - * Ko + * Ko */ static public UpnpState Ko = new UpnpState(6, "Ko"); /** - * Blacklisted + * Blacklisted */ static public UpnpState Blacklisted = new UpnpState(7, "Blacklisted"); @@ -413,34 +445,34 @@ public interface LinphoneCore { * @throws LinphoneCoreException */ public void addProxyConfig(LinphoneProxyConfig proxyCfg) throws LinphoneCoreException; - + /** * Removes a proxy configuration. * @param proxyCfg */ public void removeProxyConfig(LinphoneProxyConfig proxyCfg); - + /** * Sets the default proxy. *
- * This default proxy must be part of the list of already entered {@link LinphoneProxyConfig}. + * This default proxy must be part of the list of already entered {@link LinphoneProxyConfig}. * Toggling it as default will make LinphoneCore favor the identity associated with the proxy configuration in all incoming and outgoing calls. * Better proxy configuration match may override this choice. Pass null to unset the default proxy. - * @param proxyCfg + * @param proxyCfg */ public void setDefaultProxyConfig(LinphoneProxyConfig proxyCfg); - + /** * get he default proxy configuration, that is the one used to determine the current identity. - * @return null if no default proxy config + * @return null if no default proxy config */ public LinphoneProxyConfig getDefaultProxyConfig() ; - + /** * Returns an array with all the auth infos stored in LinphoneCore */ LinphoneAuthInfo[] getAuthInfosList(); - + /** * Returns a matching auth info or null if no match found */ @@ -450,7 +482,7 @@ public interface LinphoneCore { * @param authInfo */ public void removeAuthInfo(LinphoneAuthInfo authInfo); - + /** * clear all the added auth info */ @@ -461,7 +493,7 @@ public interface LinphoneCore { * @param info */ void addAuthInfo(LinphoneAuthInfo info); - + /** * Build an address according to the current proxy config. In case destination is not a sip address, the default proxy domain is automatically appended * @param destination @@ -469,7 +501,7 @@ public interface LinphoneCore { * @throws If no LinphoneAddress can be built from destination */ public LinphoneAddress interpretUrl(String destination) throws LinphoneCoreException; - + /** * Starts a call given a destination. Internally calls {@link #interpretUrl(String)} then {@link #invite(LinphoneAddress)}. * @param uri @@ -498,20 +530,20 @@ public interface LinphoneCore { * Returns The LinphoneCall the current call if one is in call * **/ - public LinphoneCall getCurrentCall(); - + public LinphoneCall getCurrentCall(); + /** * get current call remote address in case of in/out call * @return null if no call engaged yet */ public LinphoneAddress getRemoteAddress(); /** - * + * * @return true if there is a call running or pending. */ public boolean isIncall(); /** - * + * * @return Returns true if in incoming call is pending, ie waiting for being answered or declined. */ public boolean isInComingInvitePending(); @@ -522,7 +554,7 @@ public interface LinphoneCore { *
  • receiving of SIP messages *
  • handles timers and timeout *
  • performs registration to proxies - *
  • authentication retries The application MUST call this function from periodically, in its main loop. + *
  • 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 serialized with a mutex. */ @@ -534,10 +566,10 @@ public interface LinphoneCore { * {@link LinphoneCoreListener#callState} listener method. * The application can later respond positively to the call using * this method. - * @throws LinphoneCoreException + * @throws LinphoneCoreException */ public void acceptCall(LinphoneCall aCall) throws LinphoneCoreException; - + /** * Accept an incoming call. * @@ -545,10 +577,10 @@ public interface LinphoneCore { * {@link LinphoneCoreListener#callState} listener method. * The application can later respond positively to the call using * this method. - * @throws LinphoneCoreException + * @throws LinphoneCoreException */ public void acceptCallWithParams(LinphoneCall aCall, LinphoneCallParams params) throws LinphoneCoreException; - + /** * Accept call modifications initiated by other end. * @@ -556,11 +588,11 @@ public interface LinphoneCore { * {@link LinphoneCoreListener#callState} listener method. * The application can later respond positively to the call using * this method. - * @throws LinphoneCoreException + * @throws LinphoneCoreException */ public void acceptCallUpdate(LinphoneCall aCall, LinphoneCallParams params) throws LinphoneCoreException; - - + + /** * Prevent LinphoneCore from performing an automatic answer * @@ -568,21 +600,21 @@ public interface LinphoneCore { * {@link LinphoneCoreListener#callState} listener method. * The application can later respond positively to the call using * this method. - * @throws LinphoneCoreException + * @throws LinphoneCoreException */ public void deferCallUpdate(LinphoneCall aCall) throws LinphoneCoreException; /** - * @return a list of LinphoneCallLog + * @return a list of LinphoneCallLog */ public LinphoneCallLog[] getCallLogs(); - + /** * This method is called by the application to notify the Linphone core library when network is reachable. * Calling this method with true trigger Linphone to initiate a registration process for all proxy * configuration with parameter register set to enable. * This method disable the automatic registration mode. It means you must call this method after each network state changes - * @param network state + * @param network state * */ public void setNetworkReachable(boolean isReachable); @@ -596,12 +628,12 @@ public interface LinphoneCore { */ public void destroy(); /** - * Allow to control play level before entering sound card: + * Allow to control play level before entering sound card: * @param level in db */ public void setPlaybackGain(float gain); /** - * get play level before entering sound card: + * get play level before entering sound card: * @return level in db */ public float getPlaybackGain(); @@ -622,7 +654,7 @@ public interface LinphoneCore { */ void muteMic(boolean isMuted); /** - * + * * @return true is mic is muted */ boolean isMicMuted(); @@ -643,42 +675,42 @@ public interface LinphoneCore { * stop current dtmf */ void stopDtmf(); - + /** * remove all call logs */ void clearCallLogs(); - - - - + + + + /** * Get payload type from mime type and clock rate * * This function searches in audio and video codecs for the given payload type name and clockrate. * @param mime payload mime type (I.E SPEEX, PCMU, VP8) - * @param clockRate (I.E 8000, 16000, 90000, ...) + * @param clockRate (I.E 8000, 16000, 90000, ...) * @param channels number of channels * @return Returns null if not found. - */ - PayloadType findPayloadType(String mime, int clockRate, int channels); + */ + PayloadType findPayloadType(String mime, int clockRate, int channels); /*** * get payload type from mime type and clock rate.. * Same as @{link {@link #findPayloadType(String, int, int)} but ignoring channels params * @param mime payload mime type (I.E SPEEX, PCMU, VP8) - * @param clockRate (I.E 8000, 16000, 90000, ...) + * @param clockRate (I.E 8000, 16000, 90000, ...) * @return null if not found */ - PayloadType findPayloadType(String mime, int clockRate); - + PayloadType findPayloadType(String mime, int clockRate); + /*** - * get payload type from mime type + * get payload type from mime type * Same as @{link {@link #findPayloadType(String, int, int)} but ignoring channels and clock rate params * @param mime payload mime type (I.E SPEEX, PCMU, VP8) * @return null if not found */ - PayloadType findPayloadType(String mime); - + PayloadType findPayloadType(String mime); + /** * Enable payload type * @param pt payload type to enable, can be retrieve from {@link #findPayloadType} @@ -687,33 +719,64 @@ public interface LinphoneCore { * */ void enablePayloadType(PayloadType pt, boolean enable) throws LinphoneCoreException; - + /** - * Returns whether or not the payload is enabled in linphonecore. + * @param pt the payload type + * @return whether or not the payload is enabled in linphonecore. */ boolean isPayloadTypeEnabled(PayloadType pt); - + + /** + * @param pt the payload type + * @return whether or not the payload epresents a VBR codec + */ + boolean payloadTypeIsVbr(PayloadType pt); + /** * Set an explicit bitrate (IP bitrate, not codec bitrate) for a given codec, in kbit/s. * @param pt the payload type * @param bitrate target IP bitrate in kbit/s */ void setPayloadTypeBitrate(PayloadType pt, int bitrate); - + /** * Get target bitrate previously set by setPayloadTypeBitrate(). * @param pt * @return IP bitrate in kbit/s */ int getPayloadTypeBitrate(PayloadType pt); - + + /** + * Enable adaptive rate control. + * @param enable + */ + void enableAdaptiveRateControl(boolean enable); + + /** + * Enables or disable adaptive rate control. + * @return true if adaptive rate control is enabled. + */ + boolean isAdaptiveRateControlEnabled(); + + /** + * Sets adaptive rate algorithm. It will be used for each new calls + * starting from now. Calls already started will not be updated. + */ + void setAdaptiveRateAlgorithm(AdaptiveRateAlgorithm alg); + + /** + * Returns which adaptive rate algorithm is currently configured for + * future calls. + */ + AdaptiveRateAlgorithm getAdaptiveRateAlgorithm(); + /** * Enables or disable echo cancellation. * @param enable */ void enableEchoCancellation(boolean enable); /** - * get EC status + * get EC status * @return true if echo cancellation is enabled. */ boolean isEchoCancellationEnabled(); @@ -727,24 +790,24 @@ public interface LinphoneCore { * @param local transports ports used for signaling (TCP, UDP and TLS) */ void setSignalingTransportPorts(Transports transports); - /**Get + /**Get * @return transports used for signaling (TCP, UDP, TLS) */ Transports getSignalingTransportPorts(); - + /** * Assign a dscp value for the SIP socket. * DSCP is an IP packet field used to indicate the type of routing service to routers. * @param dscp */ void setSipDscp(int dscp); - + /** * Get DSCP used for SIP socket. * @return the DSCP value used for the SIP socket. */ int getSipDscp(); - + /** * Activates or deactivates the speaker. * @param value @@ -788,7 +851,7 @@ public interface LinphoneCore { PresenceModel getPresenceModel(); /** * Create a new chat room for messaging from a sip uri like sip:joe@sip.linphone.org - * @param to destination address for messages + * @param to destination address for messages * * @return {@link LinphoneChatRoom} where messaging can take place. */ @@ -824,18 +887,18 @@ public interface LinphoneCore { * Returns the id of the currently active video device as found in {@link AndroidCameraConfiguration#retrieveCameras}. **/ int getVideoDevice(); - - + + /** * Teturns true if the underlying sdk support video - * + * * */ boolean isVideoSupported(); - + /** * Enables video globally. * - * + * * This function does not have any effect during calls. It just indicates #LinphoneCore to * initiate future calls with video or not. The two boolean parameters indicate in which * direction video is enabled. Setting both to false disables video entirely. @@ -847,10 +910,10 @@ public interface LinphoneCore { void enableVideo(boolean vcap_enabled, boolean display_enabled); /** * Returns TRUE if video is enabled, FALSE otherwise. - * + * ***/ boolean isVideoEnabled(); - + /** * Specify a STUN server to help firewall traversal. * @param stun_server Stun server address and port, such as stun.linphone.org or stun.linphone.org:3478 @@ -861,7 +924,7 @@ public interface LinphoneCore { * @return stun server address if previously set. */ String getStunServer(); - + /** * Sets policy regarding workarounding NATs * @param pol one of the FirewallPolicy members. @@ -879,7 +942,7 @@ public interface LinphoneCore { * *
    The LinphoneAddress can be constructed directly using {@link LinphoneCoreFactory#createLinphoneAddress} , or created {@link LinphoneCore#interpretUrl(String)}. . * - * @return a {@link #LinphoneCall LinphoneCall} object + * @return a {@link #LinphoneCall LinphoneCall} object * @throws LinphoneCoreException in case of failure **/ LinphoneCall inviteAddressWithParams(LinphoneAddress destination, LinphoneCallParams params) throws LinphoneCoreException ; @@ -914,14 +977,14 @@ public interface LinphoneCore { * @return null if not set */ String getRing(); - + /** * Sets file or folder containing trusted root CAs * * @param path path to file with multiple PEM certif or to folder with multiple PEM files - */ + */ void setRootCA(String path); - + void setUploadBandwidth(int bw); /** * Sets maximum available download bandwidth @@ -936,13 +999,13 @@ public interface LinphoneCore { * @param bw the bandwidth in kbits/s, 0 for infinite */ void setDownloadBandwidth(int bw); - + /** * Sets audio packetization interval suggested for remote end. * @param ptime packetization interval in milliseconds */ void setDownloadPtime(int ptime); - + /** * Sets audio packetization interval sent to remote end. * @param ptime packetization interval in milliseconds @@ -954,7 +1017,7 @@ public interface LinphoneCore { * This applies only to the stream that is captured and sent to the remote party, * since we accept all standard video size on the receive path. * @param vSize - * + * **/ void setPreferredVideoSize(VideoSize vSize); /** @@ -971,7 +1034,7 @@ public interface LinphoneCore { * **/ VideoSize getPreferredVideoSize(); - + /** * Returns the currently supported audio codecs, as PayloadType elements * @return @@ -1004,17 +1067,17 @@ public interface LinphoneCore { * If the device has a builtin echo canceller or calibration value is already known, it will return false. */ boolean needsEchoCalibration(); - + void enableIpv6(boolean enable); - + boolean isIpv6Enabled(); - + /** * @deprecated * @param i */ void adjustSoftwareVolume(int i); - + /** * Pauses a call. If a music file has been setup using {@link LinphoneCore#setPlayFile(String)}, * this file will be played to the remote user. @@ -1029,7 +1092,7 @@ public interface LinphoneCore { * Pause all currently running calls. **/ boolean pauseAllCalls(); - + void setZrtpSecretsCache(String file); void enableEchoLimiter(boolean val); @@ -1039,12 +1102,12 @@ public interface LinphoneCore { boolean isInConference(); /** * Moves the local participant inside the conference. - * - * Makes the local participant to join the conference. + * + * Makes the local participant to join the conference. * Typically, the local participant is by default always part of the conference when joining an active call into a conference. * However, by calling {@link #leaveConference()} and {@link #enterConference()} the application can decide to temporarily * move out and in the local participant from the conference. - * + * * @returns true if successful **/ boolean enterConference(); @@ -1056,49 +1119,49 @@ public interface LinphoneCore { /** * Merge a call into a conference. - * + * * If this is the first call that enters the conference, the virtual conference will be created automatically. * If the local user was actively part of the call (ie not in paused state), then the local user is automatically entered into the conference. * If the call was in paused state, then it is automatically resumed when entering into the conference. * @param call an established call, either in {@link LinphoneCall.State#StreamsRunning} or {@link LinphoneCall.State#Paused} state. - * + * **/ void addToConference(LinphoneCall call); /** * Remove a call from the conference. * @param call a call that has been previously merged into the conference. - * + * * After removing the remote participant belonging to the supplied call, the call becomes a normal call in paused state. * If one single remote participant is left alone together with the local user in the conference after the removal, then the conference is * automatically transformed into a simple call in StreamsRunning state. * The conference's resources are then automatically destroyed. - * + * * In other words, unless {@link #leaveConference()} is explicitely called, the last remote participant of a conference is automatically * put in a simple call in running state. - * + * **/ void removeFromConference(LinphoneCall call); /** * Add all calls into a conference. - * + * * Merge all established calls (either in {@link LinphoneCall.State#StreamsRunning} or {@link LinphoneCall.State#Paused}) into a conference. - * + * **/ void addAllToConference(); - + /** * Terminates the conference and the calls associated with it. - * + * * All the calls that were merged to the conference are terminated, and the conference resources are destroyed. - * + * **/ void terminateConference(); /** * Returns the number of participants to the conference, including the local participant. - * + * * Typically, after merging two calls into the conference, there is total of 3 participants: * the local participant (or local user), and two remote participants that were the destinations of the two previously establised calls. - * + * * @returns the number of participants to the conference **/ int getConferenceSize(); @@ -1109,7 +1172,7 @@ public interface LinphoneCore { * @param path where to write recording file **/ void startConferenceRecording(String path); - + /** * Stop recording of the conference. **/ @@ -1147,7 +1210,7 @@ public interface LinphoneCore { * @param dest a running call whose remote person will receive the transfer **/ void transferCallToAnother(LinphoneCall callToTransfer, LinphoneCall destination); - + /** * Start a new call as a consequence of a transfer request received from a call. * This function is for advanced usage: the execution of transfers is automatically managed by the LinphoneCore. However if an application @@ -1185,7 +1248,7 @@ public interface LinphoneCore { * which could result in an active call. * Eg: don't start a new call if one is in outgoing ringing. * Eg: don't merge to conference either as it could result - * in two active calls (conference and accepted call). + * in two active calls (conference and accepted call). * @return */ boolean soundResourcesLocked(); @@ -1216,9 +1279,84 @@ public interface LinphoneCore { * @param path path to music file played to remote side when on hold. */ void setPlayFile(String path); + + + enum TunnelMode { + disable(0), + enable(1), + auto(2); + private final int value; + + private TunnelMode(int value){ + this.value = value; + } + public static int enumToInt(TunnelMode enum_mode) { + return enum_mode.value; + } + public static TunnelMode intToEnum(int value) { + switch(value) { + case 0: return disable; + case 1: return enable; + case 2: return auto; + default: return disable; + } + } + } + + /** + * @deprecated Use tunnelSetMode() instead + * Enable or disable tunnel + * @param enable True to enable and false to disable + */ void tunnelEnable(boolean enable); + + /** + * Set the tunnel mode. + * The tunnel can be enable or disable by passing 'enable' or 'disable'. + * If the mode is set to 'auto', Linphone will try to establish an RTP session + * on the mirror port of the tunnel server. If the connection fails, the tunnel + * will be activated. + * @param mode enable, disable or auto + */ + void tunnelSetMode(TunnelMode mode); + + /** + * Get the set mode + * @return + */ + TunnelMode tunnelGetMode(); + + /** + * Set whether sip packets must pass through the tunnel + * @param enable If true, tunnel will transport SIP packets in addition + * of RTP packets. + */ + void tunnelEnableSip(boolean enable); + + /** + * Check whether SIP tuneling is enabled + * @return true means the tunnel is set to transport SIP packets + */ + boolean tunnelSipEnabled(); + + /** + * @deprecated Use tunnelSetMode instaead + * Enable tunnel if the mirror RTP session cannot be established + */ void tunnelAutoDetect(); + + /** + * Clean the list of server + */ void tunnelCleanServers(); + + /** + * Set an optional HTTP proxy + * @param proxy_host + * @param port + * @param username + * @param password + */ void tunnelSetHttpProxy(String proxy_host, int port, String username, String password); /** * @param host tunnel server ip address @@ -1227,6 +1365,16 @@ public interface LinphoneCore { * @param roundTripDelay udp packet round trip delay in ms considered as acceptable. recommended value is 1000 ms */ void tunnelAddServerAndMirror(String host, int port, int udpMirrorPort, int roundTripDelay); + /** + * Add a server to the list of tunnel servers. + * @param config Parameters of the server to add. + */ + void tunnelAddServer(TunnelConfig config); + /** + * Returns a list of configured servers. + * @return Array of server configs. + */ + TunnelConfig[] tunnelGetServers(); boolean isTunnelAvailable(); /** @@ -1241,18 +1389,18 @@ public interface LinphoneCore { * @param autoAccept video shall be accepter by default for incoming calls **/ void setVideoPolicy(boolean autoInitiate, boolean autoAccept); - + /** * Gets the policy for the autoInitiate video */ boolean getVideoAutoInitiatePolicy(); - + /** * Gets the policy for the autoAccept video */ boolean getVideoAutoAcceptPolicy(); - - /** Set static picture to be used when "Static picture" is the video device + + /** Set static picture to be used when "Static picture" is the video device * @param path to the static picture file * */ void setStaticPicture(String path); @@ -1266,17 +1414,17 @@ public interface LinphoneCore { * Set the number of cores used for media processing * */ void setCpuCount(int count); - + /** * remove a call log */ public void removeCallLog(LinphoneCallLog log); - + /** * @return count of missed calls */ public int getMissedCallsCount(); - + /** * Set missed calls count to zero */ @@ -1290,111 +1438,111 @@ public interface LinphoneCore { * return the version code of linphone core */ public String getVersion(); - + /** * remove a linphone friend from linphone core and linphonerc */ void removeFriend(LinphoneFriend lf); - + /** * return a linphone friend (if exists) that matches the sip address */ LinphoneFriend findFriendByAddress(String sipUri); - + /** * Sets the UDP port used for audio streaming. **/ void setAudioPort(int port); - + /** * Sets the UDP port range from which to randomly select the port used for audio streaming. */ void setAudioPortRange(int minPort, int maxPort); - + /** * Assign a DSCP value to the audio RTP sockets. * @param dscp the DSCP value. * DSCP is an IP header field used to indicate a type of service to routers. */ void setAudioDscp(int dscp); - + /** * Return DSCP value used for the audio RTP sockets. * @return the DSCP value used for the audio RTP sockets. */ int getAudioDscp(); - + /** * Sets the UDP port used for video streaming. **/ void setVideoPort(int port); - + /** * Sets the UDP port range from which to randomly select the port used for video streaming. */ void setVideoPortRange(int minPort, int maxPort); - + /** * Assign a DSCP value to the video RTP sockets. * @param dscp the DSCP value. * DSCP is an IP header field used to indicate a type of service to routers. */ void setVideoDscp(int dscp); - + /** * Return DSCP value used for the video RTP sockets. * @return the DSCP value used for the video RTP sockets. */ int getVideoDscp(); - + /** * Set the incoming call timeout in seconds. * If an incoming call isn't answered for this timeout period, it is * automatically declined. **/ void setIncomingTimeout(int timeout); - + /** * Set the call timeout in seconds. * Once this time is elapsed (ringing included), the call is automatically hung up. **/ void setInCallTimeout(int timeout); /** - * Allow to control microphone level: + * Allow to control microphone level: * @param gain in db **/ void setMicrophoneGain(float gain); - + /** * Set username and display name to use if no LinphoneProxyConfig configured */ void setPrimaryContact(String displayName, String username); - + /** * Returns the username used if no LinphoneProxyConfig configured */ String getPrimaryContactUsername(); - + /** * Returns the display name used if no LinphoneProxyConfig configured */ String getPrimaryContactDisplayName(); - + /** * Enable/Disable the use of SIP INFO for DTMFs */ void setUseSipInfoForDtmfs(boolean use); - + /** * Returns the state of use of SIP INFO for DTMFs */ boolean getUseSipInfoForDtmfs(); - + /** * Enable/Disable the use of inband DTMFs */ void setUseRfc2833ForDtmfs(boolean use); - + /** * Returns the state of use of inband DTMFs */ @@ -1410,34 +1558,34 @@ public interface LinphoneCore { /** * Return the availability of uPnP. * - * @return true if uPnP is available otherwise return false. + * @return true if uPnP is available otherwise return false. */ public boolean upnpAvailable(); /** - * Return the internal state of uPnP. + * Return the internal state of uPnP. * - * @return an UpnpState. + * @return an UpnpState. */ public UpnpState getUpnpState(); /** - * Return the external ip address of router. + * Return the external ip address of router. * In some cases the uPnP can have an external ip address but not a usable uPnP - * (state different of Ok). + * (state different of Ok). * * @return a null terminated string containing the external ip address. If the - * the external ip address is not available return null. + * the external ip address is not available return null. */ public String getUpnpExternalIpaddress(); - + /** * Create an empty INFO message. * It can later be sent using {@link LinphoneCall.sendInfoMessage() }. * @return the new info message. */ public LinphoneInfoMessage createInfoMessage(); - + /** * Sends an outgoing subscription for a resource with given event, expiration period, and content. * The state changes of the new subscriptions can be followed thanks to { @link LinphoneCoreListener.subscriptionStateChanged() } and @@ -1449,7 +1597,7 @@ public interface LinphoneCore { * @return a LinphoneEvent representing the subscription context. */ public LinphoneEvent subscribe(LinphoneAddress resource, String event, int expires, LinphoneContent content); - + /** * Create an outgoing subscription, specifying the destination resource, the event name, and an optional content body. * If accepted, the subscription runs for a finite period, but is automatically renewed if not terminated before. @@ -1461,7 +1609,7 @@ public interface LinphoneCore { * @return a LinphoneEvent holding the context of the created subcription. */ public LinphoneEvent createSubscribe(LinphoneAddress resource, String event, int expires); - + /** * Create a publish context for an event state. * After being created, the publish must be sent using linphone_event_send_publish(). @@ -1472,7 +1620,7 @@ public interface LinphoneCore { * @return the LinphoneEvent holding the context of the publish. */ public LinphoneEvent createPublish(LinphoneAddress resource, String event, int expires); - + /** * Publish an event. * After the initial publication, updates can be done with { @link LinphoneEvent.updatePublish() } @@ -1483,25 +1631,25 @@ public interface LinphoneCore { * @return a LinphoneEvent representing the publish context. */ public LinphoneEvent publish(LinphoneAddress resource, String event, int expires, LinphoneContent content); - + /** * Sets the path to the database where the chat messages will be stored (if enabled) * @param path the database where the chat messages will be stored. */ public void setChatDatabasePath(String path); - + /** * Gets the chat rooms * @return an array of LinphoneChatRoom */ public LinphoneChatRoom[] getChatRooms(); - + /** * Gets the linphonecore supported resolutions for video * @return an array of String */ public String[] getSupportedVideoSizes(); - + /** * Migrate configuration so that all SIP transports are enabled. * Versions of linphone < 3.7 did not support using multiple SIP transport simultaneously. @@ -1511,7 +1659,7 @@ public interface LinphoneCore { * @returns 1 if migration was done, 0 if not done because unnecessary or already done, -1 in case of error. */ public int migrateToMultiTransport(); - + /** * When receiving an incoming, accept to start a media session as early-media. * This means the call is not accepted but audio & video streams can be established if the remote party supports early media. @@ -1523,7 +1671,7 @@ public interface LinphoneCore { * @return true if successful, false otherwise. */ public boolean acceptEarlyMedia(LinphoneCall call); - + /** * Accept an early media session for an incoming call. * This is identical as calling linphone_core_accept_early_media_with_params() with NULL call parameters. @@ -1533,28 +1681,29 @@ public interface LinphoneCore { * @return true if successful, false otherwise. */ public boolean acceptEarlyMediaWithParams(LinphoneCall call, LinphoneCallParams params); - + /** * Creates a proxy config using the default values if they exists * @return a default proxy config */ public LinphoneProxyConfig createProxyConfig(); - + public LinphoneProxyConfig createProxyConfig(String identity,String proxy,String route, boolean enableRegister) throws LinphoneCoreException; + /** * Assign an audio file to played locally upon call failure, for a given reason. * @param reason the #LinphoneReason representing the failure error code. * @param path a wav file to be played when such call failure happens. */ public void setCallErrorTone(Reason reason, String path); - + /** * Assign an audio file to be played locally in replacement of common telephony tone. * This is typically used to internationalize tones. * @param id a tone id - * @param wav a path to a 16 bit PCM linear wav file. + * @param wav a path to a 16 bit PCM linear wav file. */ public void setTone(ToneID id, String wavfile); - + /** * Inform the core about the maximum transmission unit of the network. * This is used for fragmenting video RTP packets to a size compatible with the network. @@ -1563,7 +1712,7 @@ public interface LinphoneCore { public void setMtu(int mtu); /** * Returns the mtu value previously set by setMtu(). - * + * * @return the MTU in bytes. */ public int getMtu(); @@ -1577,31 +1726,59 @@ public interface LinphoneCore { * @return true if INVITE has to be sent whitout SDP. */ public boolean isSdp200AckEnabled(); - + /** * Inconditionnaly disable incoming chat messages. * @param lc the core * @param deny_reason the deny reason (using ReasonNone has no effect). **/ public void disableChat(Reason denycode); - + /** * Enable reception of incoming chat messages. * By default it is enabled but it can be disabled with linphone_core_disable_chat(). * @param lc the core **/ public void enableChat(); - + /** * Returns whether chat is enabled. * @return true if chat is enabled, false otherwise. **/ public boolean chatEnabled(); - + /** - * Whenever the liblinphone is playing a ring to advertise an incoming call or ringback of an outgoing call, this function stops the ringing. + * Whenever the liblinphone is playing a ring to advertise an incoming call or ringback of an outgoing call, this function stops the ringing. * Typical use is to stop ringing when the user requests to ignore the call. **/ public void stopRinging(); + + /** + * Set audio jitter buffer size in milliseconds. + * A value of zero disables the jitter buffer. + * The new value is taken into account immediately for all running or pending calls. + * @param value the jitter buffer size in milliseconds. + */ + public void setAudioJittcomp(int value); + + /** + * Set video jitter buffer size in milliseconds. + * A value of zero disables the jitter buffer. + * The new value is taken into account immediately for all running or pending calls. + * @param value the jitter buffer size in milliseconds. + */ + public void setVideoJittcomp(int value); + + /** + * Globaly set an http file transfer server to be used for content type application/vnd.gsma.rcs-ft-http+xml. + * @param serverUrl URL of the file server like https://file.linphone.org/upload.php + */ + public void setFileTransferServer(String serverUrl); + + /** + * Get the globaly set http file transfer server to be used for content type application/vnd.gsma.rcs-ft-http+xml. + * @return the serverUrl + */ + public String getFileTransferServer(); } diff --git a/java/common/org/linphone/core/LinphoneCoreFactory.java b/java/common/org/linphone/core/LinphoneCoreFactory.java index 5838594dc..a26f95b9a 100644 --- a/java/common/org/linphone/core/LinphoneCoreFactory.java +++ b/java/common/org/linphone/core/LinphoneCoreFactory.java @@ -104,12 +104,10 @@ abstract public class LinphoneCoreFactory { abstract public LinphoneAddress createLinphoneAddress(String address) throws LinphoneCoreException; abstract public LpConfig createLpConfig(String file); - abstract public LinphoneProxyConfig createProxyConfig(String identity, String proxy,String route,boolean enableRegister) throws LinphoneCoreException; - /** * Enable verbose traces - * @param enable - * @param tag + * @param enable true to enable debug mode, false to disable it + * @param tag Tag which prefixes each log message. */ abstract public void setDebugMode(boolean enable, String tag); diff --git a/java/common/org/linphone/core/LinphoneCoreListener.java b/java/common/org/linphone/core/LinphoneCoreListener.java index bd83172a9..c82390c48 100644 --- a/java/common/org/linphone/core/LinphoneCoreListener.java +++ b/java/common/org/linphone/core/LinphoneCoreListener.java @@ -18,6 +18,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.linphone.core; +import java.nio.ByteBuffer; + import org.linphone.core.LinphoneCore.RemoteProvisioningState; @@ -188,6 +190,35 @@ public interface LinphoneCoreListener { /** @Deprecated Callback to display a warning to the user * @return */ void displayWarning(LinphoneCore lc,String message); - + + /** + * Callback to be notified about the transfer progress. + * @param lc the LinphoneCore + * @param message the LinphoneChatMessage + * @param content the LinphoneContent + * @param progress percentage of the transfer done + */ + void fileTransferProgressIndication(LinphoneCore lc, LinphoneChatMessage message, LinphoneContent content, int progress); + + /** + * Callback to be notified when new data has been received + * @param lc the LinphoneCore + * @param message the LinphoneChatMessage + * @param content the LinphoneContent + * @param buffer + * @param size + */ + void fileTransferRecv(LinphoneCore lc, LinphoneChatMessage message, LinphoneContent content, byte[] buffer, int size); + + /** + * Callback to be notified when new data needs to be sent + * @param lc the LinphoneCore + * @param message the LinphoneChatMessage + * @param content the LinphoneContent + * @param buffer + * @param size + * @return the number of bytes written into buffer + */ + int fileTransferSend(LinphoneCore lc, LinphoneChatMessage message, LinphoneContent content, ByteBuffer buffer, int size); } diff --git a/java/common/org/linphone/core/LinphoneProxyConfig.java b/java/common/org/linphone/core/LinphoneProxyConfig.java index c2c742bd4..8b668da2e 100644 --- a/java/common/org/linphone/core/LinphoneProxyConfig.java +++ b/java/common/org/linphone/core/LinphoneProxyConfig.java @@ -18,19 +18,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package org.linphone.core; /** - * The LinphoneProxyConfig object represents a proxy configuration to be used by the LinphoneCore object. Its fields must not be used directly in favour of the accessors methods. + * The LinphoneProxyConfig object represents a proxy configuration to be used by the LinphoneCore object. Its fields must not be used directly in favour of the accessors methods. * Once created and filled properly the LinphoneProxyConfig can be given to LinphoneCore with {@link LinphoneCore#addProxyConfig(LinphoneProxyConfig)}. This will automatically triggers the registration, if enabled. *
    The proxy configuration are persistent to restarts because they are saved in the configuration file. As a consequence, after {@link LinphoneCoreFactory#createLinphoneCore(LinphoneCoreListener, String, String, Object)} there might already be a default proxy that can be examined with {@link LinphoneCore#getDefaultProxyConfig()} . * */ public interface LinphoneProxyConfig { - - public void setIsDeleted(boolean b); - public boolean getIsDeleted(); - + /** *Starts editing a proxy configuration. - *Because proxy configuration must be consistent, applications MUST call {@link #edit()} before doing any attempts to modify proxy configuration (such as identity, proxy address and so on). + *Because proxy configuration must be consistent, applications MUST call {@link #edit()} before doing any attempts to modify proxy configuration (such as identity, proxy address and so on). *Once the modifications are done, then the application must call {@link #done()} to commit the changes. */ public LinphoneProxyConfig edit(); @@ -61,20 +58,20 @@ public interface LinphoneProxyConfig { public void setProxy(String proxyUri) throws LinphoneCoreException; /** * get the proxy's SIP address. - * + * */ public String getProxy(); /** * Enable register for this proxy config. * Register message is issued after call to {@link #done()} * @param value - */ + */ public LinphoneProxyConfig enableRegister(boolean value); /** * @return true if registration to the proxy is enabled. */ public boolean registerEnabled(); - + /** * normalize a human readable phone number into a basic string. 888-444-222 becomes 888444222 * @param number @@ -86,32 +83,32 @@ public interface LinphoneProxyConfig { * @param prefix */ public void setDialPrefix(String prefix); - + /** * Returns the automatically added international prefix to e164 phone numbers */ public String getDialPrefix(); - + /** * * Sets whether liblinphone should replace "+" by "00" in dialed numbers (passed to * {@link LinphoneCore#invite(String)}). * @param value default value is false */ public void setDialEscapePlus(boolean value); - + /** * Whether liblinphone should replace "+" by "00" in dialed numbers (passed to * {@link LinphoneCore#invite(String)}). */ public boolean getDialEscapePlus(); - + /** * get domain host name or ip * @return may be null */ public String getDomain(); /** - * + * * @return a boolean indicating that the user is successfully registered on the proxy. */ public boolean isRegistered(); @@ -122,7 +119,7 @@ public interface LinphoneProxyConfig { */ public void setRoute(String routeUri) throws LinphoneCoreException; /** - * + * * @return the route set for this proxy configuration. */ public String getRoute(); @@ -138,95 +135,108 @@ public interface LinphoneProxyConfig { * 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); - + /** * Gets the registration expiration time. * @return delay expiration time in seconds. */ int getExpires(); - + /** * Set the privacy for all calls or chat sessions using the identity exposed by this LinphoneProxyConfig * @param privacy_mask a or'd int of values defined in interface {@link org.linphone.core.Privacy} */ void setPrivacy(int privacy_mask); - + /** * Get the privacy mask requested for this proxy config. * @return the privacy mask as defined in interface {@link org.linphone.core.Privacy} */ int getPrivacy(); - + /** * Indicates whether AVPF/SAVPF must be used for calls using this proxy config. * @param enable True to enable AVPF/SAVF, false to disable it. */ void enableAvpf(boolean enable); - + /** * Whether AVPF is used for calls through this proxy. - * @return + * @return */ boolean avpfEnabled(); - + /** * Set the interval between regular RTCP reports when using AVPF/SAVPF. * @param interval The interval in seconds (between 0 and 5 seconds). */ void setAvpfRRInterval(int interval); - + /** * Get the interval between regular RTCP reports when using AVPF/SAVPF. * @return The interval in seconds. */ int getAvpfRRInterval(); - + /** * Indicates whether quality reporting must be used for calls using this proxy config. * @param enable True to enable quality reporting, false to disable it. */ void enableQualityReporting(boolean enable); - + /** * Whether quality reporting is used for calls through this proxy. - * @return + * @return */ boolean qualityReportingEnabled(); - + /** * Set the interval between quality interval reports during a call when using quality reporting. * @param interval The interval in seconds (should be greater than 120 seconds to avoid too much). */ void setQualityReportingInterval(int interval); - + /** * Get the interval between quality interval reports during a call when using quality reporting. * @return The interval in seconds. */ int getQualityReportingInterval(); - + /** * Set the collector SIP URI to collect reports when using quality reporting. * @param collector The collector SIP URI which should be configured server side too. */ void setQualityReportingCollector(String collector); - + /** * Get the collector SIP URI collecting reports when using quality reporting. * @return The SIP URI collector address. */ String getQualityReportingCollector(); - + + /** + * Set the outbound proxy realm. It is used in digest authentication to avoid + * re-authentication if a previous token has already been provided. + * @param The new outbound proxy realm. + */ + void setRealm(String realm); + + /** + * Get the outbound proxy realm. + * @return The outbound proxy realm. + */ + String getRealm(); + /** * Set optional contact parameters that will be added to the contact information sent in the registration. * @param contact_params a string containing the additional parameters in text form, like "myparam=something;myparam2=something_else" @@ -235,13 +245,13 @@ public interface LinphoneProxyConfig { * As an example, the contact address in the SIP register sent will look like ;android-push-id=43143-DFE23F-2323-FA2232. **/ public void setContactParameters(String contact_params); - + /** * Get the contact's parameters. * @return */ public String getContactParameters(); - + /** * Set optional contact parameters that will be added to the contact information sent in the registration, inside the URI. * @param params a string containing the additional parameters in text form, like "myparam=something;myparam2=something_else" @@ -250,34 +260,55 @@ public interface LinphoneProxyConfig { * As an example, the contact address in the SIP register sent will look like . **/ public void setContactUriParameters(String params); - + /** * Get the contact's URI parameters. * @return */ public String getContactUriParameters(); - + /** * Return the international prefix for the given country * @param country iso code */ public int lookupCCCFromIso(String iso); - + /** * Return the international prefix for the given country * @param e164 phone number */ public int lookupCCCFromE164(String e164); - + /** * Return reason error code. * @return reason code. */ public Reason getError(); - + /** * Get full error information about last error occured on the proxy config. * @return an ErrorInfo. */ public ErrorInfo getErrorInfo(); + + /** + * Set the publish expiration time in second. + * @param expires in second + */ + public void setPublishExpires(int expires); + /** + * @return the publish expiration time in second. Default value is the registration expiration value. + */ + public int getPublishExpires(); + + /** + * attached a user data to a proxy config + **/ + void setUserData(Object obj); + + /** + * Returns user data from a proxy config. return null if any + * @return an Object. + */ + Object getUserData(); } diff --git a/java/impl/org/linphone/core/LinphoneAuthInfoImpl.java b/java/impl/org/linphone/core/LinphoneAuthInfoImpl.java index 7d2b3dde2..8efdcc144 100644 --- a/java/impl/org/linphone/core/LinphoneAuthInfoImpl.java +++ b/java/impl/org/linphone/core/LinphoneAuthInfoImpl.java @@ -37,7 +37,7 @@ class LinphoneAuthInfoImpl implements LinphoneAuthInfo { boolean ownPtr = false; protected LinphoneAuthInfoImpl(String username,String password, String realm, String domain) { - this(username, null, password, null, null, domain); + this(username, null, password, null, realm, domain); } protected LinphoneAuthInfoImpl(String username, String userid, String passwd, String ha1, String realm, String domain) { nativePtr = newLinphoneAuthInfo(); @@ -46,6 +46,7 @@ class LinphoneAuthInfoImpl implements LinphoneAuthInfo { this.setPassword(passwd); this.setHa1(ha1); this.setDomain(domain); + this.setRealm(realm); ownPtr = true; } protected LinphoneAuthInfoImpl(long aNativePtr) { diff --git a/java/impl/org/linphone/core/LinphoneCallImpl.java b/java/impl/org/linphone/core/LinphoneCallImpl.java index 66a9bf1d9..ee78e9d89 100644 --- a/java/impl/org/linphone/core/LinphoneCallImpl.java +++ b/java/impl/org/linphone/core/LinphoneCallImpl.java @@ -22,6 +22,7 @@ class LinphoneCallImpl implements LinphoneCall { protected final long nativePtr; boolean ownPtr = false; + Object userData; private LinphoneCallStats audioStats; private LinphoneCallStats videoStats; @@ -236,4 +237,12 @@ class LinphoneCallImpl implements LinphoneCall { public ErrorInfo getErrorInfo() { return new ErrorInfoImpl(getErrorInfo(nativePtr)); } + @Override + public void setUserData(Object obj) { + userData = obj; + } + @Override + public Object getUserData() { + return userData; + } } diff --git a/java/impl/org/linphone/core/LinphoneChatMessageImpl.java b/java/impl/org/linphone/core/LinphoneChatMessageImpl.java index c48c8a5cc..d25ae426a 100644 --- a/java/impl/org/linphone/core/LinphoneChatMessageImpl.java +++ b/java/impl/org/linphone/core/LinphoneChatMessageImpl.java @@ -48,6 +48,12 @@ public class LinphoneChatMessageImpl implements LinphoneChatMessage { return new LinphoneAddressImpl(getFrom(nativePtr),LinphoneAddressImpl.WrapMode.FromConst); } + private native long getTo(long ptr); + @Override + public LinphoneAddress getTo() { + return new LinphoneAddressImpl(getTo(nativePtr),LinphoneAddressImpl.WrapMode.FromConst); + } + private native void addCustomHeader(long nativePtr, String name, String value); @Override public void addCustomHeader(String name, String value) { @@ -93,7 +99,32 @@ public class LinphoneChatMessageImpl implements LinphoneChatMessage { public ErrorInfo getErrorInfo() { return new ErrorInfoImpl(getErrorInfo(nativePtr)); } - protected void finalize(){ + protected void finalize() throws Throwable{ unref(nativePtr); + super.finalize(); + } + + private native void startFileDownload(long ptr, StateListener listener); + @Override + public void startFileDownload(StateListener listener) { + startFileDownload(nativePtr, listener); + } + + private native Object getFileTransferInformation(long ptr); + @Override + public LinphoneContent getFileTransferInformation() { + return (LinphoneContent) getFileTransferInformation(nativePtr); + } + + private native void setAppData(long ptr, String data); + @Override + public void setAppData(String data) { + setAppData(nativePtr, data); + } + + private native String getAppData(long ptr); + @Override + public String getAppData() { + return getAppData(nativePtr); } } diff --git a/java/impl/org/linphone/core/LinphoneChatRoomImpl.java b/java/impl/org/linphone/core/LinphoneChatRoomImpl.java index 8aa9c258d..d47e4e47e 100644 --- a/java/impl/org/linphone/core/LinphoneChatRoomImpl.java +++ b/java/impl/org/linphone/core/LinphoneChatRoomImpl.java @@ -27,9 +27,11 @@ class LinphoneChatRoomImpl implements LinphoneChatRoom { private native long getPeerAddress(long ptr); private native void sendMessage(long ptr, String message); private native void sendMessage2(long ptr, Object msg, long messagePtr, StateListener listener); + private native long[] getHistoryRange(long ptr, int begin, int end); private native long[] getHistory(long ptr, int limit); private native void destroy(long ptr); private native int getUnreadMessagesCount(long ptr); + private native int getHistorySize(long ptr); private native void deleteHistory(long ptr); private native void compose(long ptr); private native boolean isRemoteComposing(long ptr); @@ -44,100 +46,106 @@ class LinphoneChatRoomImpl implements LinphoneChatRoom { nativePtr = aNativePtr; } - public synchronized LinphoneAddress getPeerAddress() { + public LinphoneAddress getPeerAddress() { return new LinphoneAddressImpl(getPeerAddress(nativePtr),LinphoneAddressImpl.WrapMode.FromConst); } - public synchronized void sendMessage(String message) { + public void sendMessage(String message) { synchronized(getCore()){ sendMessage(nativePtr,message); } } - + @Override - public synchronized void sendMessage(LinphoneChatMessage message, StateListener listener) { + public void sendMessage(LinphoneChatMessage message, StateListener listener) { synchronized(getCore()){ sendMessage2(nativePtr, message, ((LinphoneChatMessageImpl)message).getNativePtr(), listener); } } @Override - public synchronized LinphoneChatMessage createLinphoneChatMessage(String message) { + public LinphoneChatMessage createLinphoneChatMessage(String message) { synchronized(getCore()){ return new LinphoneChatMessageImpl(createLinphoneChatMessage(nativePtr, message)); } } - - public synchronized LinphoneChatMessage[] getHistory() { + + public LinphoneChatMessage[] getHistory() { synchronized(getCore()){ return getHistory(0); } } - - public synchronized LinphoneChatMessage[] getHistory(int limit) { + + public LinphoneChatMessage[] getHistoryRange(int begin, int end) { synchronized(getCore()){ - long[] typesPtr = getHistory(nativePtr, limit); - if (typesPtr == null) return null; - - LinphoneChatMessage[] messages = new LinphoneChatMessage[typesPtr.length]; - for (int i=0; i < messages.length; i++) { - messages[i] = new LinphoneChatMessageImpl(typesPtr[i]); - } - - return messages; + long[] typesPtr = getHistoryRange(nativePtr, begin, end); + return getHistoryPrivate(typesPtr); } } - - public synchronized void destroy() { + + public LinphoneChatMessage[] getHistory(int limit) { + synchronized(getCore()){ + long[] typesPtr = getHistory(nativePtr, limit); + return getHistoryPrivate(typesPtr); + } + } + + public void destroy() { destroy(nativePtr); } - - public synchronized int getUnreadMessagesCount() { + + public int getUnreadMessagesCount() { synchronized(getCore()){ return getUnreadMessagesCount(nativePtr); } } - - public synchronized void deleteHistory() { + + public int getHistorySize() { + synchronized(getCore()){ + return getHistorySize(nativePtr); + } + } + + public void deleteHistory() { synchronized(getCore()){ deleteHistory(nativePtr); } } - public synchronized void compose() { + public void compose() { synchronized(getCore()){ compose(nativePtr); } } - public synchronized boolean isRemoteComposing() { + public boolean isRemoteComposing() { synchronized(getCore()){ return isRemoteComposing(nativePtr); } } - - public synchronized void markAsRead() { + + public void markAsRead() { synchronized(getCore()){ markAsRead(nativePtr); } } - - public synchronized void deleteMessage(LinphoneChatMessage message) { + + public void deleteMessage(LinphoneChatMessage message) { synchronized(getCore()){ if (message != null) deleteMessage(nativePtr, ((LinphoneChatMessageImpl)message).getNativePtr()); } } - - public synchronized void updateUrl(LinphoneChatMessage message) { + + public void updateUrl(LinphoneChatMessage message) { synchronized(getCore()){ if (message != null) updateUrl(nativePtr, ((LinphoneChatMessageImpl)message).getNativePtr()); } } - + @Override - public synchronized LinphoneChatMessage createLinphoneChatMessage(String message, + public LinphoneChatMessage createLinphoneChatMessage(String message, String url, State state, long timestamp, boolean isRead, boolean isIncoming) { synchronized(getCore()){ @@ -150,4 +158,30 @@ class LinphoneChatRoomImpl implements LinphoneChatRoom { public synchronized LinphoneCore getCore() { return (LinphoneCore)getCore(nativePtr); } + private LinphoneChatMessage[] getHistoryPrivate(long[] typesPtr) { + if (typesPtr == null) return null; + + LinphoneChatMessage[] messages = new LinphoneChatMessage[typesPtr.length]; + for (int i=0; i < messages.length; i++) { + messages[i] = new LinphoneChatMessageImpl(typesPtr[i]); + } + + return messages; + } + + private native long createFileTransferMessage(long ptr, String name, String type, String subtype, int size); + @Override + public LinphoneChatMessage createFileTransferMessage(LinphoneContent content) { + synchronized(getCore()) { + return new LinphoneChatMessageImpl(createFileTransferMessage(nativePtr, content.getName(), content.getType(), content.getSubtype(), content.getRealSize())); + } + } + + private native void cancelFileTransfer(long ptr, long messagePtr); + @Override + public void cancelFileTransfer(LinphoneChatMessage message) { + synchronized(getCore()) { + cancelFileTransfer(nativePtr, ((LinphoneChatMessageImpl)message).getNativePtr()); + } + } } diff --git a/java/impl/org/linphone/core/LinphoneContentImpl.java b/java/impl/org/linphone/core/LinphoneContentImpl.java index b12e6580f..0231fd539 100644 --- a/java/impl/org/linphone/core/LinphoneContentImpl.java +++ b/java/impl/org/linphone/core/LinphoneContentImpl.java @@ -1,14 +1,26 @@ package org.linphone.core; public class LinphoneContentImpl implements LinphoneContent { - private String mType, mSubtype, mEncoding; + private String mType, mSubtype, mEncoding, mName; private byte[] mData; + private int mExpectedSize; - public LinphoneContentImpl(String type, String subtype, byte data[], String encoding ){ - mType=type; - mSubtype=subtype; - mData=data; - mEncoding=encoding; + public LinphoneContentImpl(String type, String subtype, byte data[], String encoding){ + mType = type; + mSubtype = subtype; + mData = data; + mEncoding = encoding; + mName = null; + mExpectedSize = 0; + } + + public LinphoneContentImpl(String name, String type, String subtype, byte data[], String encoding, int expectedSize){ + mType = type; + mSubtype = subtype; + mData = data; + mEncoding = encoding; + mName = name; + mExpectedSize = expectedSize; } @Override @@ -23,32 +35,49 @@ public class LinphoneContentImpl implements LinphoneContent { @Override public String getDataAsString() { - return new String(mData); + if (mData != null) + return new String(mData); + return null; + } + + @Override + public void setExpectedSize(int size) { + mExpectedSize = size; } @Override - public int getSize() { - return mData.length; + public int getExpectedSize() { + return mExpectedSize; + } + + @Override + public int getRealSize() { + if (mData != null) + return mData.length; + return 0; } @Override public void setType(String type) { - mType=type; + mType = type; } @Override public void setSubtype(String subtype) { - mSubtype=subtype; + mSubtype = subtype; } @Override public void setStringData(String data) { - mData=data.getBytes(); + if (data != null) + mData = data.getBytes(); + else + mData = null; } @Override public void setData(byte data[]){ - mData=data; + mData = data; } @Override @@ -63,7 +92,16 @@ public class LinphoneContentImpl implements LinphoneContent { @Override public void setEncoding(String encoding) { - mEncoding=encoding; + mEncoding = encoding; } + @Override + public void setName(String name) { + mName = name; + } + + @Override + public String getName() { + return mName; + } } diff --git a/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java b/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java index 85bff8ffa..f0d3ae064 100644 --- a/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java +++ b/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java @@ -108,12 +108,6 @@ public class LinphoneCoreFactoryImpl extends LinphoneCoreFactory { } } - @Override - public LinphoneProxyConfig createProxyConfig(String identity, String proxy, - String route, boolean enableRegister) throws LinphoneCoreException { - return new LinphoneProxyConfigImpl(identity,proxy,route,enableRegister); - } - @Override public native void setDebugMode(boolean enable, String tag); diff --git a/java/impl/org/linphone/core/LinphoneCoreImpl.java b/java/impl/org/linphone/core/LinphoneCoreImpl.java index eeebbd328..0c53735fc 100644 --- a/java/impl/org/linphone/core/LinphoneCoreImpl.java +++ b/java/impl/org/linphone/core/LinphoneCoreImpl.java @@ -34,19 +34,19 @@ import android.media.AudioManager; class LinphoneCoreImpl implements LinphoneCore { private final LinphoneCoreListener mListener; //to make sure to keep a reference on this object - private long nativePtr = 0; + protected long nativePtr = 0; private Context mContext = null; private AudioManager mAudioManager = null; private boolean mSpeakerEnabled = false; private native long newLinphoneCore(LinphoneCoreListener listener,String userConfig,String factoryConfig,Object userdata); private native void iterate(long nativePtr); - private native long getDefaultProxyConfig(long nativePtr); + private native LinphoneProxyConfig getDefaultProxyConfig(long nativePtr); private native void setDefaultProxyConfig(long nativePtr,long proxyCfgNativePtr); private native int addProxyConfig(LinphoneProxyConfig jprtoxyCfg,long nativePtr,long proxyCfgNativePtr); private native void removeProxyConfig(long nativePtr, long proxyCfg); private native void clearAuthInfos(long nativePtr); - + private native void clearProxyConfigs(long nativePtr); private native void addAuthInfo(long nativePtr,long authInfoNativePtr); private native void removeAuthInfo(long nativePtr, long authInfoNativePtr); @@ -73,6 +73,11 @@ class LinphoneCoreImpl implements LinphoneCore { private native long findPayloadType(long nativePtr, String mime, int clockRate, int channels); private native int enablePayloadType(long nativePtr, long payloadType, boolean enable); private native boolean isPayloadTypeEnabled(long nativePtr, long payloadType); + private native boolean payloadTypeIsVbr(long nativePtr, long payloadType); + private native void enableAdaptiveRateControl(long nativePtr,boolean enable); + private native boolean isAdaptiveRateControlEnabled(long nativePtr); + private native String getAdaptiveRateAlgorithm(long nativePtr); + private native void setAdaptiveRateAlgorithm(long nativePtr, String alg); private native void enableEchoCancellation(long nativePtr,boolean enable); private native boolean isEchoCancellationEnabled(long nativePtr); private native Object getCurrentCall(long nativePtr) ; @@ -145,12 +150,12 @@ class LinphoneCoreImpl implements LinphoneCore { private native void setChatDatabasePath(long nativePtr, String path); private native long[] getChatRooms(long nativePtr); private native int migrateToMultiTransport(long nativePtr); - private native long createProxyConfig(long nativePtr); private native void setCallErrorTone(long nativePtr, int reason, String path); private native void enableSdp200Ack(long nativePtr,boolean enable); private native boolean isSdp200AckEnabled(long nativePtr); private native void stopRinging(long nativePtr); - + private native static void setAndroidPowerManager(Object pm); + LinphoneCoreImpl(LinphoneCoreListener listener, File userConfig, File factoryConfig, Object userdata) throws IOException { mListener = listener; String user = userConfig == null ? null : userConfig.getCanonicalPath(); @@ -161,9 +166,9 @@ class LinphoneCoreImpl implements LinphoneCore { mListener = listener; nativePtr = newLinphoneCore(listener,null,null,null); } - + protected void finalize() throws Throwable { - + if (nativePtr!=0) destroy(); } private boolean contextInitialized() { @@ -176,6 +181,7 @@ class LinphoneCoreImpl implements LinphoneCore { public void setContext(Object context) { mContext = (Context)context; mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); + setAndroidPowerManager(mContext.getSystemService(Context.POWER_SERVICE)); } public synchronized void addAuthInfo(LinphoneAuthInfo info) { @@ -190,12 +196,7 @@ class LinphoneCoreImpl implements LinphoneCore { public synchronized LinphoneProxyConfig getDefaultProxyConfig() { isValid(); - long lNativePtr = getDefaultProxyConfig(nativePtr); - if (lNativePtr!=0) { - return new LinphoneProxyConfigImpl(this,lNativePtr); - } else { - return null; - } + return getDefaultProxyConfig(nativePtr); } public synchronized LinphoneCall invite(String uri) { @@ -223,8 +224,6 @@ class LinphoneCoreImpl implements LinphoneCore { public synchronized void removeProxyConfig(LinphoneProxyConfig proxyCfg) { isValid(); removeProxyConfig(nativePtr, ((LinphoneProxyConfigImpl)proxyCfg).nativePtr); - ((LinphoneProxyConfigImpl)proxyCfg).mCore=null; - ((LinphoneProxyConfigImpl)proxyCfg).deleteNativePtr(); } public synchronized void clearAuthInfos() { isValid(); @@ -261,18 +260,17 @@ class LinphoneCoreImpl implements LinphoneCore { } public synchronized LinphoneCallLog[] getCallLogs() { isValid(); - LinphoneCallLog[] logs = new LinphoneCallLog[getNumberOfCallLogs(nativePtr)]; + LinphoneCallLog[] logs = new LinphoneCallLog[getNumberOfCallLogs(nativePtr)]; for (int i=0;i < getNumberOfCallLogs(nativePtr);i++) { logs[i] = new LinphoneCallLogImpl(getCallLog(nativePtr, i)); } return logs; } public synchronized void destroy() { - isValid(); delete(nativePtr); - nativePtr = 0; + nativePtr=0; } - + private void isValid() { if (nativePtr == 0) { throw new RuntimeException("object already destroyed"); @@ -283,7 +281,7 @@ class LinphoneCoreImpl implements LinphoneCore { } public synchronized void setPlaybackGain(float gain) { setPlaybackGain(nativePtr,gain); - + } public synchronized float getPlaybackGain() { return getPlaybackGain(nativePtr); @@ -300,7 +298,7 @@ class LinphoneCoreImpl implements LinphoneCore { throw new LinphoneCoreException("Cannot interpret ["+destination+"]"); } } - public synchronized LinphoneCall invite(LinphoneAddress to) throws LinphoneCoreException { + public synchronized LinphoneCall invite(LinphoneAddress to) throws LinphoneCoreException { LinphoneCall call = (LinphoneCall)inviteAddress(nativePtr,((LinphoneAddressImpl)to).nativePtr); if (call!=null) { return call; @@ -333,12 +331,18 @@ class LinphoneCoreImpl implements LinphoneCore { if (enablePayloadType(nativePtr,((PayloadTypeImpl)pt).nativePtr,enable) != 0) { throw new LinphoneCoreException("cannot enable payload type ["+pt+"]"); } - + } public synchronized boolean isPayloadTypeEnabled(PayloadType pt) { isValid(); return isPayloadTypeEnabled(nativePtr, ((PayloadTypeImpl)pt).nativePtr); } + + public synchronized boolean payloadTypeIsVbr(PayloadType pt) { + isValid(); + return payloadTypeIsVbr(nativePtr, ((PayloadTypeImpl)pt).nativePtr); + } + public synchronized void enableEchoCancellation(boolean enable) { isValid(); enableEchoCancellation(nativePtr, enable); @@ -346,21 +350,21 @@ class LinphoneCoreImpl implements LinphoneCore { public synchronized boolean isEchoCancellationEnabled() { isValid(); return isEchoCancellationEnabled(nativePtr); - + } public synchronized LinphoneCall getCurrentCall() { isValid(); return (LinphoneCall)getCurrentCall(nativePtr); } - + public int getPlayLevel() { // TODO Auto-generated method stub return 0; } public void setPlayLevel(int level) { // TODO Auto-generated method stub - + } private void applyAudioHacks() { @@ -396,20 +400,20 @@ class LinphoneCoreImpl implements LinphoneCore { } public synchronized void playDtmf(char number, int duration) { playDtmf(nativePtr,number, duration); - + } public synchronized void stopDtmf() { stopDtmf(nativePtr); } - + public synchronized void addFriend(LinphoneFriend lf) throws LinphoneCoreException { addFriend(nativePtr,((LinphoneFriendImpl)lf).nativePtr); - + } @SuppressWarnings("deprecation") public synchronized void setPresenceInfo(int minutes_away, String alternative_contact, OnlineStatus status) { setPresenceInfo(nativePtr,minutes_away,alternative_contact,status.mValue); - + } @SuppressWarnings("deprecation") public synchronized OnlineStatus getPresenceInfo() { @@ -433,7 +437,7 @@ class LinphoneCoreImpl implements LinphoneCore { public synchronized void setDeviceRotation(int rotation) { setDeviceRotation(nativePtr, rotation); } - + public synchronized void enableVideo(boolean vcap_enabled, boolean display_enabled) { enableVideo(nativePtr,vcap_enabled, display_enabled); } @@ -455,15 +459,15 @@ class LinphoneCoreImpl implements LinphoneCore { public synchronized void setStunServer(String stunServer) { setStunServer(nativePtr,stunServer); } - + public synchronized LinphoneCallParams createDefaultCallParameters() { return new LinphoneCallParamsImpl(createDefaultCallParams(nativePtr)); } - + public synchronized LinphoneCall inviteAddressWithParams(LinphoneAddress to, LinphoneCallParams params) throws LinphoneCoreException { long ptrDestination = ((LinphoneAddressImpl)to).nativePtr; long ptrParams =((LinphoneCallParamsImpl)params).nativePtr; - + LinphoneCall call = (LinphoneCall)inviteAddressWithParams(nativePtr, ptrDestination, ptrParams); if (call!=null) { return call; @@ -508,19 +512,19 @@ class LinphoneCoreImpl implements LinphoneCore { public synchronized String getRing() { return getRing(nativePtr); } - + public synchronized void setRootCA(String path) { setRootCA(nativePtr, path); } - - public synchronized LinphoneProxyConfig[] getProxyConfigList() { + + public synchronized LinphoneProxyConfig[] getProxyConfigList() { return getProxyConfigList(nativePtr); } - + public synchronized PayloadType[] getVideoCodecs() { long[] typesPtr = listVideoPayloadTypes(nativePtr); if (typesPtr == null) return null; - + PayloadType[] codecs = new PayloadType[typesPtr.length]; for (int i=0; i < codecs.length; i++) { @@ -532,7 +536,7 @@ class LinphoneCoreImpl implements LinphoneCore { public synchronized PayloadType[] getAudioCodecs() { long[] typesPtr = listAudioPayloadTypes(nativePtr); if (typesPtr == null) return null; - + PayloadType[] codecs = new PayloadType[typesPtr.length]; for (int i=0; i < codecs.length; i++) { @@ -544,10 +548,10 @@ class LinphoneCoreImpl implements LinphoneCore { public synchronized boolean isNetworkReachable() { return isNetworkStateReachable(nativePtr); } - + public synchronized void enableKeepAlive(boolean enable) { enableKeepAlive(nativePtr,enable); - + } public synchronized boolean isKeepAliveEnabled() { return isKeepAliveEnabled(nativePtr); @@ -555,7 +559,7 @@ class LinphoneCoreImpl implements LinphoneCore { public synchronized void startEchoCalibration(Object data) throws LinphoneCoreException { startEchoCalibration(nativePtr, data); } - + public synchronized Transports getSignalingTransportPorts() { Transports transports = new Transports(); transports.udp = getSignalingTransportPort(nativePtr, 0); @@ -590,7 +594,7 @@ class LinphoneCoreImpl implements LinphoneCore { } public synchronized void setDownloadPtime(int ptime) { setDownloadPtime(nativePtr,ptime); - + } public synchronized void setUploadPtime(int ptime) { setUploadPtime(nativePtr,ptime); @@ -613,12 +617,12 @@ class LinphoneCoreImpl implements LinphoneCore { } - private native void leaveConference(long nativePtr); + private native void leaveConference(long nativePtr); public synchronized void leaveConference() { leaveConference(nativePtr); } - private native boolean enterConference(long nativePtr); + private native boolean enterConference(long nativePtr); public synchronized boolean enterConference() { return enterConference(nativePtr); } @@ -656,12 +660,12 @@ class LinphoneCoreImpl implements LinphoneCore { private native void addAllToConference(long nativePtr); public synchronized void addAllToConference() { addAllToConference(nativePtr); - + } private native void addToConference(long nativePtr, long nativePtrLcall); public synchronized void addToConference(LinphoneCall call) { addToConference(nativePtr, getCallPtr(call)); - + } private native void removeFromConference(long nativePtr, long nativeCallPtr); public synchronized void removeFromConference(LinphoneCall call) { @@ -671,7 +675,7 @@ class LinphoneCoreImpl implements LinphoneCore { private long getCallPtr(LinphoneCall call) { return ((LinphoneCallImpl)call).nativePtr; } - + private long getCallParamsPtr(LinphoneCallParams callParams) { return ((LinphoneCallParamsImpl)callParams).nativePtr; } @@ -699,7 +703,7 @@ class LinphoneCoreImpl implements LinphoneCore { return isMediaEncryptionMandatory(nativePtr); } public synchronized void setMediaEncryption(MediaEncryption menc) { - setMediaEncryption(nativePtr, menc.mValue); + setMediaEncryption(nativePtr, menc.mValue); } public synchronized void setMediaEncryptionMandatory(boolean yesno) { setMediaEncryptionMandatory(nativePtr, yesno); @@ -751,6 +755,18 @@ class LinphoneCoreImpl implements LinphoneCore { tunnelAddServerAndMirror(nativePtr, host, port, mirror, ms); } + private native void tunnelAddServer(long nativePtr, TunnelConfig config); + @Override + public synchronized void tunnelAddServer(TunnelConfig config) { + tunnelAddServer(nativePtr, config); + } + + private native final TunnelConfig[] tunnelGetServers(long nativePtr); + @Override + public synchronized final TunnelConfig[] tunnelGetServers() { + return tunnelGetServers(nativePtr); + } + private native void tunnelAutoDetect(long nativePtr); @Override public synchronized void tunnelAutoDetect() { @@ -768,10 +784,34 @@ class LinphoneCoreImpl implements LinphoneCore { public synchronized void tunnelEnable(boolean enable) { tunnelEnable(nativePtr, enable); } + + private native void tunnelSetMode(long nativePtr, int mode); + @Override + public synchronized void tunnelSetMode(LinphoneCore.TunnelMode mode) { + tunnelSetMode(nativePtr, TunnelMode.enumToInt(mode)); + } + + private native int tunnelGetMode(long nativePtr); + @Override + public synchronized LinphoneCore.TunnelMode tunnelGetMode() { + return LinphoneCore.TunnelMode.intToEnum(tunnelGetMode(nativePtr)); + } + + private native void tunnelEnableSip(long nativePtr, boolean enable); + @Override + public void tunnelEnableSip(boolean enable) { + tunnelEnableSip(nativePtr, enable); + } + + private native boolean tunnelSipEnabled(long nativePtr); + @Override + public boolean tunnelSipEnabled() { + return tunnelSipEnabled(nativePtr); + } @Override public native boolean isTunnelAvailable(); - + private native void acceptCallWithParams(long nativePtr, long aCall, long params); @Override @@ -779,14 +819,14 @@ class LinphoneCoreImpl implements LinphoneCore { LinphoneCallParams params) throws LinphoneCoreException { acceptCallWithParams(nativePtr, getCallPtr(aCall), getCallParamsPtr(params)); } - + private native void acceptCallUpdate(long nativePtr, long aCall, long params); @Override public synchronized void acceptCallUpdate(LinphoneCall aCall, LinphoneCallParams params) throws LinphoneCoreException { - acceptCallUpdate(nativePtr, getCallPtr(aCall), getCallParamsPtr(params)); + acceptCallUpdate(nativePtr, getCallPtr(aCall), getCallParamsPtr(params)); } - + private native void deferCallUpdate(long nativePtr, long aCall); @Override public synchronized void deferCallUpdate(LinphoneCall aCall) @@ -794,7 +834,7 @@ class LinphoneCoreImpl implements LinphoneCore { deferCallUpdate(nativePtr, getCallPtr(aCall)); } - + private native void setVideoPolicy(long nativePtr, boolean autoInitiate, boolean autoAccept); public synchronized void setVideoPolicy(boolean autoInitiate, boolean autoAccept) { setVideoPolicy(nativePtr, autoInitiate, autoAccept); @@ -807,7 +847,7 @@ class LinphoneCoreImpl implements LinphoneCore { public synchronized boolean getVideoAutoAcceptPolicy() { return getVideoAutoAcceptPolicy(nativePtr); } - + private native void setStaticPicture(long nativePtr, String path); public synchronized void setStaticPicture(String path) { setStaticPicture(nativePtr, path); @@ -823,11 +863,11 @@ class LinphoneCoreImpl implements LinphoneCore { { setCpuCountNative(count); } - + public synchronized int getMissedCallsCount() { return getMissedCallsCount(nativePtr); } - + public synchronized void removeCallLog(LinphoneCallLog log) { removeCallLog(nativePtr, ((LinphoneCallLogImpl) log).getNativePtr()); } @@ -835,7 +875,7 @@ class LinphoneCoreImpl implements LinphoneCore { public synchronized void resetMissedCallsCount() { resetMissedCallsCount(nativePtr); } - + private native void tunnelSetHttpProxy(long nativePtr, String proxy_host, int port, String username, String password); @Override @@ -843,12 +883,12 @@ class LinphoneCoreImpl implements LinphoneCore { String username, String password) { tunnelSetHttpProxy(nativePtr, proxy_host, port, username, password); } - + private native void refreshRegisters(long nativePtr); public synchronized void refreshRegisters() { refreshRegisters(nativePtr); } - + @Override public String getVersion() { return getVersion(nativePtr); @@ -865,13 +905,13 @@ class LinphoneCoreImpl implements LinphoneCore { public synchronized PayloadType findPayloadType(String mime, int clockRate) { return findPayloadType(mime, clockRate, FIND_PAYLOAD_IGNORE_CHANNELS); } - + private native void removeFriend(long ptr, long lf); @Override public synchronized void removeFriend(LinphoneFriend lf) { removeFriend(nativePtr, lf.getNativePtr()); } - + private native long getFriendByAddress(long ptr, String sipUri); @Override public synchronized LinphoneFriend findFriendByAddress(String sipUri) { @@ -881,64 +921,64 @@ class LinphoneCoreImpl implements LinphoneCore { } return new LinphoneFriendImpl(ptr); } - + public synchronized void setAudioPort(int port) { setAudioPort(nativePtr, port); } - + public synchronized void setVideoPort(int port) { setVideoPort(nativePtr, port); } - + public synchronized void setAudioPortRange(int minPort, int maxPort) { setAudioPortRange(nativePtr, minPort, maxPort); } - + public synchronized void setVideoPortRange(int minPort, int maxPort) { setVideoPortRange(nativePtr, minPort, maxPort); } - + public synchronized void setIncomingTimeout(int timeout) { setIncomingTimeout(nativePtr, timeout); } - + public synchronized void setInCallTimeout(int timeout) { setInCallTimeout(nativePtr, timeout); } - + private native void setMicrophoneGain(long ptr, float gain); public synchronized void setMicrophoneGain(float gain) { setMicrophoneGain(nativePtr, gain); } - + public synchronized void setPrimaryContact(String displayName, String username) { setPrimaryContact(nativePtr, displayName, username); } - + public synchronized String getPrimaryContactUsername() { return getPrimaryContactUsername(nativePtr); } - + public synchronized String getPrimaryContactDisplayName() { return getPrimaryContactDisplayName(nativePtr); } - + private native void setUseSipInfoForDtmfs(long ptr, boolean use); public synchronized void setUseSipInfoForDtmfs(boolean use) { setUseSipInfoForDtmfs(nativePtr, use); } - + private native boolean getUseSipInfoForDtmfs(long ptr); public synchronized boolean getUseSipInfoForDtmfs() { return getUseSipInfoForDtmfs(nativePtr); } - + private native void setUseRfc2833ForDtmfs(long ptr, boolean use); public synchronized void setUseRfc2833ForDtmfs(boolean use) { setUseRfc2833ForDtmfs(nativePtr, use); } - + private native boolean getUseRfc2833ForDtmfs(long ptr); public synchronized boolean getUseRfc2833ForDtmfs() { return getUseRfc2833ForDtmfs(nativePtr); @@ -959,17 +999,17 @@ class LinphoneCoreImpl implements LinphoneCore { public synchronized void declineCall(LinphoneCall aCall, Reason reason) { declineCall(nativePtr,((LinphoneCallImpl)aCall).nativePtr,reason.mValue); } - + private native boolean upnpAvailable(long ptr); public synchronized boolean upnpAvailable() { return upnpAvailable(nativePtr); - } + } private native int getUpnpState(long ptr); public synchronized UpnpState getUpnpState() { - return UpnpState.fromInt(getUpnpState(nativePtr)); + return UpnpState.fromInt(getUpnpState(nativePtr)); } - + private native String getUpnpExternalIpaddress(long ptr); public synchronized String getUpnpExternalIpaddress() { return getUpnpExternalIpaddress(nativePtr); @@ -979,7 +1019,7 @@ class LinphoneCoreImpl implements LinphoneCore { public synchronized void startConferenceRecording(String path) { startConferenceRecording(nativePtr,path); } - + private native int stopConferenceRecording(long nativePtr); @Override public synchronized void stopConferenceRecording() { @@ -989,13 +1029,13 @@ class LinphoneCoreImpl implements LinphoneCore { public synchronized PayloadType findPayloadType(String mime) { return findPayloadType(mime, FIND_PAYLOAD_IGNORE_RATE); } - + private native void setSipDscp(long nativePtr, int dscp); @Override public synchronized void setSipDscp(int dscp) { setSipDscp(nativePtr,dscp); } - + private native int getSipDscp(long nativePtr); @Override public synchronized int getSipDscp() { @@ -1006,36 +1046,36 @@ class LinphoneCoreImpl implements LinphoneCore { public synchronized void setAudioDscp(int dscp) { setAudioDscp(nativePtr, dscp); } - + private native int getAudioDscp(long nativePtr); @Override public synchronized int getAudioDscp() { return getAudioDscp(nativePtr); } - + private native void setVideoDscp(long nativePtr, int dscp); @Override public synchronized void setVideoDscp(int dscp) { setVideoDscp(nativePtr,dscp); } - + private native int getVideoDscp(long nativePtr); @Override public synchronized int getVideoDscp() { return getVideoDscp(nativePtr); } - + private native long createInfoMessage(long nativeptr); @Override public synchronized LinphoneInfoMessage createInfoMessage() { return new LinphoneInfoMessageImpl(createInfoMessage(nativePtr)); } - + private native Object subscribe(long coreptr, long addrptr, String eventname, int expires, String type, String subtype, byte data [], String encoding); @Override public synchronized LinphoneEvent subscribe(LinphoneAddress resource, String eventname, int expires, LinphoneContent content) { - return (LinphoneEvent)subscribe(nativePtr, ((LinphoneAddressImpl)resource).nativePtr, eventname, expires, + return (LinphoneEvent)subscribe(nativePtr, ((LinphoneAddressImpl)resource).nativePtr, eventname, expires, content!=null ? content.getType() : null, content!=null ? content.getSubtype() : null, content!=null ? content.getData() : null, content!=null ? content.getEncoding() : null); } @@ -1043,7 +1083,7 @@ class LinphoneCoreImpl implements LinphoneCore { @Override public synchronized LinphoneEvent publish(LinphoneAddress resource, String eventname, int expires, LinphoneContent content) { - return (LinphoneEvent)publish(nativePtr, ((LinphoneAddressImpl)resource).nativePtr, eventname, expires, + return (LinphoneEvent)publish(nativePtr, ((LinphoneAddressImpl)resource).nativePtr, eventname, expires, content!=null ? content.getType() : null, content!=null ? content.getSubtype() : null, content!=null ? content.getData() : null, content!=null ? content.getEncoding() : null); } @@ -1060,15 +1100,15 @@ class LinphoneCoreImpl implements LinphoneCore { String event, int expires) { return (LinphoneEvent)createPublish(nativePtr, ((LinphoneAddressImpl)resource).nativePtr, event, expires); } - + public synchronized void setChatDatabasePath(String path) { setChatDatabasePath(nativePtr, path); } - + public synchronized LinphoneChatRoom[] getChatRooms() { long[] typesPtr = getChatRooms(nativePtr); if (typesPtr == null) return null; - + LinphoneChatRoom[] proxies = new LinphoneChatRoom[typesPtr.length]; for (int i=0; i < proxies.length; i++) { @@ -1080,7 +1120,7 @@ class LinphoneCoreImpl implements LinphoneCore { public synchronized LinphoneAuthInfo[] getAuthInfosList() { long[] typesPtr = getAuthInfosList(nativePtr); if (typesPtr == null) return null; - + LinphoneAuthInfo[] authInfos = new LinphoneAuthInfo[typesPtr.length]; for (int i=0; i < authInfos.length; i++) { @@ -1089,12 +1129,12 @@ class LinphoneCoreImpl implements LinphoneCore { return authInfos; } - + public synchronized LinphoneAuthInfo findAuthInfo(String username, String realm, String domain) { long ptr = findAuthInfos(nativePtr, username, realm, domain); if (ptr == 0) return null; - + return new LinphoneAuthInfoImpl(ptr); } private native LinphoneCall startReferedCall(long corePtr, long callptr, long paramsPtr); @@ -1104,7 +1144,7 @@ class LinphoneCoreImpl implements LinphoneCore { long ptrParams =((LinphoneCallParamsImpl)params).nativePtr; return startReferedCall(nativePtr, getCallPtr(call), ptrParams); } - + private native String[] listSupportedVideoResolutions(long ptr); @Override public synchronized String[] getSupportedVideoSizes() { @@ -1115,13 +1155,13 @@ class LinphoneCoreImpl implements LinphoneCore { public synchronized int migrateToMultiTransport() { return migrateToMultiTransport(nativePtr); } - + private native boolean acceptEarlyMedia(long lc, long call); @Override public synchronized boolean acceptEarlyMedia(LinphoneCall call) { return acceptEarlyMedia(nativePtr, getCallPtr(call)); } - + private native boolean acceptEarlyMediaWithParams(long lc, long call, long params); @Override public synchronized boolean acceptEarlyMediaWithParams(LinphoneCall call, @@ -1131,7 +1171,16 @@ class LinphoneCoreImpl implements LinphoneCore { } @Override public synchronized LinphoneProxyConfig createProxyConfig() { - return new LinphoneProxyConfigImpl(this,createProxyConfig(nativePtr)); + return new LinphoneProxyConfigImpl(this); + } + @Override + public synchronized LinphoneProxyConfig createProxyConfig(String identity,String proxy,String route, boolean enableRegister) throws LinphoneCoreException { + isValid(); + try { + return new LinphoneProxyConfigImpl(this,identity,proxy,route,enableRegister); + } catch(LinphoneCoreException e){ + return null; + } } @Override public synchronized void setCallErrorTone(Reason reason, String path) { @@ -1175,7 +1224,7 @@ class LinphoneCoreImpl implements LinphoneCore { public synchronized boolean chatEnabled() { return chatEnabled(nativePtr); } - + @Override public synchronized void stopRinging() { stopRinging(nativePtr); @@ -1190,5 +1239,44 @@ class LinphoneCoreImpl implements LinphoneCore { public synchronized int getPayloadTypeBitrate(PayloadType pt) { return getPayloadTypeBitrate(nativePtr, ((PayloadTypeImpl)pt).nativePtr); } + @Override + public synchronized void enableAdaptiveRateControl(boolean enable) { + enableAdaptiveRateControl(nativePtr,enable); + + } + @Override + public synchronized boolean isAdaptiveRateControlEnabled() { + return isAdaptiveRateControlEnabled(nativePtr); + } + public synchronized AdaptiveRateAlgorithm getAdaptiveRateAlgorithm() { + return AdaptiveRateAlgorithm.fromString(getAdaptiveRateAlgorithm(nativePtr)); + } + public synchronized void setAdaptiveRateAlgorithm(AdaptiveRateAlgorithm alg) { + setAdaptiveRateAlgorithm(nativePtr, alg.toString()); + } + + + private native void setAudioJittcomp(long ptr, int value); + @Override + public synchronized void setAudioJittcomp(int value) { + setAudioJittcomp(nativePtr,value); + } + private native void setVideoJittcomp(long ptr, int value); + @Override + public synchronized void setVideoJittcomp(int value) { + setVideoJittcomp(nativePtr,value); + } + private native void setFileTransferServer(long ptr, String serverUrl); + @Override + public synchronized void setFileTransferServer(String serverUrl) { + setFileTransferServer(nativePtr, serverUrl); + } + + private native String getFileTransferServer(long ptr); + @Override + public synchronized String getFileTransferServer() { + return getFileTransferServer(nativePtr); + } + } diff --git a/java/impl/org/linphone/core/LinphoneEventImpl.java b/java/impl/org/linphone/core/LinphoneEventImpl.java index ca9c2151c..c78b5da40 100644 --- a/java/impl/org/linphone/core/LinphoneEventImpl.java +++ b/java/impl/org/linphone/core/LinphoneEventImpl.java @@ -33,7 +33,7 @@ public class LinphoneEventImpl implements LinphoneEvent { private native int notify(long nativeptr, String type, String subtype, byte data[], String encoding); @Override - public synchronized void notify(LinphoneContent content) { + public void notify(LinphoneContent content) { synchronized(getCore()){ notify(mNativePtr,content.getType(),content.getSubtype(),content.getData(),content.getEncoding()); } @@ -41,7 +41,7 @@ public class LinphoneEventImpl implements LinphoneEvent { private native int updateSubscribe(long nativePtr, String type, String subtype, byte data[], String encoding); @Override - public synchronized void updateSubscribe(LinphoneContent content) { + public void updateSubscribe(LinphoneContent content) { synchronized(getCore()){ updateSubscribe(mNativePtr,content.getType(), content.getSubtype(),content.getData(),content.getEncoding()); } @@ -49,7 +49,7 @@ public class LinphoneEventImpl implements LinphoneEvent { private native int updatePublish(long nativePtr, String type, String subtype, byte data[], String encoding); @Override - public synchronized void updatePublish(LinphoneContent content) { + public void updatePublish(LinphoneContent content) { synchronized(getCore()){ updatePublish(mNativePtr,content.getType(), content.getSubtype(),content.getData(),content.getEncoding()); } @@ -57,7 +57,7 @@ public class LinphoneEventImpl implements LinphoneEvent { private native int terminate(long nativePtr); @Override - public synchronized void terminate() { + public void terminate() { synchronized(getCore()){ terminate(mNativePtr); } @@ -115,7 +115,7 @@ public class LinphoneEventImpl implements LinphoneEvent { private native void sendSubscribe(long ptr, String type, String subtype, byte data [], String encoding); @Override - public synchronized void sendSubscribe(LinphoneContent body) { + public void sendSubscribe(LinphoneContent body) { synchronized(getCore()){ if (body != null) sendSubscribe(mNativePtr, body.getType(), body.getSubtype(), body.getData(), body.getEncoding()); @@ -126,7 +126,7 @@ public class LinphoneEventImpl implements LinphoneEvent { private native void sendPublish(long ptr, String type, String subtype, byte data [], String encoding); @Override - public synchronized void sendPublish(LinphoneContent body) { + public void sendPublish(LinphoneContent body) { synchronized(getCore()){ if (body != null) sendPublish(mNativePtr, body.getType(), body.getSubtype(), body.getData(), body.getEncoding()); diff --git a/java/impl/org/linphone/core/LinphoneProxyConfigImpl.java b/java/impl/org/linphone/core/LinphoneProxyConfigImpl.java index 475fe352d..f08980190 100644 --- a/java/impl/org/linphone/core/LinphoneProxyConfigImpl.java +++ b/java/impl/org/linphone/core/LinphoneProxyConfigImpl.java @@ -22,42 +22,33 @@ import org.linphone.core.LinphoneCore.RegistrationState; class LinphoneProxyConfigImpl implements LinphoneProxyConfig { - protected long nativePtr; + protected final long nativePtr; protected LinphoneCoreImpl mCore; - protected boolean isDeleting; - + Object userData; + + private native void finalize(long ptr); private native int getState(long nativePtr); private native void setExpires(long nativePtr, int delay); private native int getExpires(long nativePtr); + private native long createProxyConfig( long nativePtr); - boolean ownPtr = false; - protected LinphoneProxyConfigImpl(String identity,String proxy,String route, boolean enableRegister) throws LinphoneCoreException { - nativePtr = newLinphoneProxyConfig(); + protected LinphoneProxyConfigImpl(LinphoneCoreImpl core,String identity,String proxy,String route, boolean enableRegister) throws LinphoneCoreException { + mCore=core; + nativePtr = createProxyConfig(core.nativePtr); setIdentity(identity); setProxy(proxy); setRoute(route); - setIsDeleted(false); enableRegister(enableRegister); - ownPtr=true; } - protected LinphoneProxyConfigImpl(LinphoneCoreImpl core,long aNativePtr) { + protected LinphoneProxyConfigImpl(LinphoneCoreImpl core) { + mCore=core; + nativePtr = createProxyConfig(core.nativePtr); + } + /*reserved for JNI */ + protected LinphoneProxyConfigImpl(LinphoneCoreImpl core, long aNativePtr) { mCore=core; nativePtr = aNativePtr; - ownPtr=false; - } - - protected LinphoneProxyConfigImpl(long aNativePtr) { - nativePtr = aNativePtr; - ownPtr=false; - } - - public boolean getIsDeleted() { - return isDeleting; - } - - public void setIsDeleted(boolean b) { - isDeleting = b; } private void isValid() { @@ -66,16 +57,13 @@ class LinphoneProxyConfigImpl implements LinphoneProxyConfig { } } - public void deleteNativePtr() { - nativePtr=0; - } - protected void finalize() throws Throwable { - //Log.e(LinphoneService.TAG,"fixme, should release underlying proxy config"); - if (ownPtr) delete(nativePtr); + if (nativePtr != 0) { + finalize(nativePtr); + } + super.finalize(); } private native long newLinphoneProxyConfig(); - private native void delete(long ptr); private native void edit(long ptr); private native void done(long ptr); @@ -212,7 +200,7 @@ class LinphoneProxyConfigImpl implements LinphoneProxyConfig { } public boolean publishEnabled() { isValid(); - return publishEnabled(nativePtr); + return publishEnabled(nativePtr); } @Override public void setContactParameters(String params) { @@ -304,21 +292,21 @@ class LinphoneProxyConfigImpl implements LinphoneProxyConfig { public ErrorInfo getErrorInfo() { return new ErrorInfoImpl(getErrorInfo(nativePtr)); } - + private native void enableQualityReporting(long nativePtr, boolean enable); @Override public void enableQualityReporting(boolean enable) { isValid(); enableQualityReporting(nativePtr, enable); } - + private native boolean qualityReportingEnabled(long nativePtr); @Override public boolean qualityReportingEnabled() { isValid(); return avpfEnabled(nativePtr); } - + private native void setQualityReportingInterval(long nativePtr, int interval); @Override public void setQualityReportingInterval(int interval) { @@ -331,6 +319,7 @@ class LinphoneProxyConfigImpl implements LinphoneProxyConfig { isValid(); return getQualityReportingInterval(nativePtr); } + private native void setQualityReportingCollector(long nativePtr, String collector); @Override public void setQualityReportingCollector(String collector) { @@ -344,4 +333,41 @@ class LinphoneProxyConfigImpl implements LinphoneProxyConfig { isValid(); return getQualityReportingCollector(nativePtr); } + + private native void setRealm(long nativePtr, String realm); + @Override + public void setRealm(String realm) { + isValid(); + setRealm(nativePtr, realm); + } + private native String getRealm(long nativePtr); + @Override + public String getRealm() { + + isValid(); + return getRealm(nativePtr); + } + + private native void setPublishExpires(long nativePtr, int expires); + @Override + public void setPublishExpires(int expires) { + isValid(); + setPublishExpires(nativePtr, expires); + } + private native int getPublishExpires(long nativePtr); + @Override + public int getPublishExpires() { + + isValid(); + return getPublishExpires(nativePtr); + } + + @Override + public void setUserData(Object obj) { + userData = obj; + } + @Override + public Object getUserData() { + return userData; + } } diff --git a/java/impl/org/linphone/core/TunnelConfig.java b/java/impl/org/linphone/core/TunnelConfig.java new file mode 100644 index 000000000..9801f0fbd --- /dev/null +++ b/java/impl/org/linphone/core/TunnelConfig.java @@ -0,0 +1,40 @@ +package org.linphone.core; + +public class TunnelConfig { + private String host = null; + private int port = 443; + private int remoteUdpMirrorPort = 12345; + private int delay = 1000; + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + public int getRemoteUdpMirrorPort() { + return remoteUdpMirrorPort; + } + + public void setRemoteUdpMirrorPort(int remoteUdpMirrorPort) { + this.remoteUdpMirrorPort = remoteUdpMirrorPort; + } + + public int getDelay() { + return delay; + } + + public void setDelay(int delay) { + this.delay = delay; + } +} diff --git a/mediastreamer2 b/mediastreamer2 index b40af312e..21e35e89f 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit b40af312e90b6c91bbee360f430ed87fa26119e9 +Subproject commit 21e35e89ffa8920bb0b5865d365b84471ecfa321 diff --git a/oRTP b/oRTP index 99f33a0f5..45da3ab75 160000 --- a/oRTP +++ b/oRTP @@ -1 +1 @@ -Subproject commit 99f33a0f510310389c22bf88a39582450be38425 +Subproject commit 45da3ab75d39587189ea95829ee1cb92d61827be diff --git a/po/cs.po b/po/cs.po index 048bb9624..78c993c32 100644 --- a/po/cs.po +++ b/po/cs.po @@ -18,7 +18,7 @@ msgid "" msgstr "" "Project-Id-Version: linphone-3.5.99.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-01 21:24+0200\n" +"POT-Creation-Date: 2014-09-15 09:24+0200\n" "PO-Revision-Date: 2013-05-01 09:55+0200\n" "Last-Translator: Petr Pisar \n" "Language-Team: Czech \n" @@ -28,12 +28,12 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" -#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:973 +#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:974 #, c-format msgid "Call %s" msgstr "Volat komu: %s" -#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:974 +#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:975 #, c-format msgid "Send text to %s" msgstr "Poslat text komu: %s" @@ -43,23 +43,23 @@ msgstr "Poslat text komu: %s" msgid "Recent calls (%i)" msgstr "Nedávné hovory (%i)" -#: ../gtk/calllogs.c:312 +#: ../gtk/calllogs.c:314 msgid "n/a" msgstr "–" -#: ../gtk/calllogs.c:315 +#: ../gtk/calllogs.c:317 msgid "Aborted" msgstr "Přerušen" -#: ../gtk/calllogs.c:318 +#: ../gtk/calllogs.c:320 msgid "Missed" msgstr "Zmeškán" -#: ../gtk/calllogs.c:321 +#: ../gtk/calllogs.c:323 msgid "Declined" msgstr "Odmítnut" -#: ../gtk/calllogs.c:327 +#: ../gtk/calllogs.c:329 #, c-format msgid "%i minute" msgid_plural "%i minutes" @@ -67,7 +67,7 @@ msgstr[0] "%i minuta" msgstr[1] "%i minuty" msgstr[2] "%i minut" -#: ../gtk/calllogs.c:330 +#: ../gtk/calllogs.c:332 #, c-format msgid "%i second" msgid_plural "%i seconds" @@ -75,12 +75,12 @@ msgstr[0] "%i sekunda" msgstr[1] "%i sekundy" msgstr[2] "%i sekund" -#: ../gtk/calllogs.c:333 ../gtk/calllogs.c:339 +#: ../gtk/calllogs.c:335 ../gtk/calllogs.c:341 #, c-format msgid "%s\t%s" msgstr "%s\t%s" -#: ../gtk/calllogs.c:335 +#: ../gtk/calllogs.c:337 #, c-format msgid "" "%s\tQuality: %s\n" @@ -89,7 +89,7 @@ msgstr "" "%s\tKvalita: %s\n" "%s\t%s\t" -#: ../gtk/calllogs.c:341 +#: ../gtk/calllogs.c:343 #, c-format msgid "" "%s\t\n" @@ -111,7 +111,7 @@ msgstr "Já" msgid "Couldn't find pixmap file: %s" msgstr "Nelze najít soubor s obrázkem: %s" -#: ../gtk/chat.c:363 ../gtk/friendlist.c:923 +#: ../gtk/chat.c:364 ../gtk/friendlist.c:924 msgid "Invalid sip contact !" msgstr "Neplatný sipový kontakt!" @@ -162,7 +162,7 @@ msgstr "Průvodce nastavením účtu" msgid "Call with %s" msgstr "Hovor s %s" -#: ../gtk/main.c:1171 +#: ../gtk/main.c:1183 #, c-format msgid "" "%s would like to add you to his contact list.\n" @@ -175,7 +175,7 @@ msgstr "" "do svého adresáře?\n" "Odpovíte-li ne, tato osobo bude dočasně blokována." -#: ../gtk/main.c:1248 +#: ../gtk/main.c:1260 #, fuzzy, c-format msgid "" "Please enter your password for username %s\n" @@ -184,59 +184,59 @@ msgstr "" "Prosím, zadejte heslo pro uživatele %s\n" "v doméně %s:" -#: ../gtk/main.c:1364 +#: ../gtk/main.c:1376 msgid "Call error" msgstr "Chyba hovoru" -#: ../gtk/main.c:1367 ../coreapi/linphonecore.c:3515 +#: ../gtk/main.c:1379 ../coreapi/linphonecore.c:3240 msgid "Call ended" msgstr "Hovor ukončen" -#: ../gtk/main.c:1370 ../coreapi/linphonecore.c:254 +#: ../gtk/main.c:1382 msgid "Incoming call" msgstr "Příchozí hovor" -#: ../gtk/main.c:1372 ../gtk/incall_view.c:513 ../gtk/main.ui.h:5 +#: ../gtk/main.c:1384 ../gtk/incall_view.c:522 ../gtk/main.ui.h:5 msgid "Answer" msgstr "Odpovědět" -#: ../gtk/main.c:1374 ../gtk/main.ui.h:6 +#: ../gtk/main.c:1386 ../gtk/main.ui.h:6 msgid "Decline" msgstr "Odmítnout" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 msgid "Call paused" msgstr "Hovor odložen" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, c-format msgid "by %s" msgstr "kým: %s" -#: ../gtk/main.c:1447 +#: ../gtk/main.c:1459 #, c-format msgid "%s proposed to start video. Do you accept ?" msgstr "%s navrhuje začít videohovor. Přijímáte?" -#: ../gtk/main.c:1609 +#: ../gtk/main.c:1621 msgid "Website link" msgstr "Odkaz na webovou stránku" -#: ../gtk/main.c:1658 +#: ../gtk/main.c:1670 msgid "Linphone - a video internet phone" msgstr "Lipnhone – internetový videofon" -#: ../gtk/main.c:1750 +#: ../gtk/main.c:1762 #, c-format msgid "%s (Default)" msgstr "%s (Výchozí)" -#: ../gtk/main.c:2086 ../coreapi/callbacks.c:927 +#: ../gtk/main.c:2099 ../coreapi/callbacks.c:949 #, c-format msgid "We are transferred to %s" msgstr "Byly jsme přepojeni na %s" -#: ../gtk/main.c:2096 +#: ../gtk/main.c:2109 msgid "" "No sound cards have been detected on this computer.\n" "You won't be able to send or receive audio calls." @@ -244,7 +244,7 @@ msgstr "" "Na tomto počítači nebyla objevena žádná zvuková karta.\n" "Nebudete moci vytáčet a přijímat a zvukové hovory." -#: ../gtk/main.c:2237 +#: ../gtk/main.c:2250 msgid "A free SIP video-phone" msgstr "Volný SIP videofon" @@ -256,7 +256,7 @@ msgstr "Přidat do adresáře" msgid "Presence status" msgstr "Stav" -#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:550 ../gtk/contact.ui.h:1 +#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:552 ../gtk/contact.ui.h:1 msgid "Name" msgstr "Jméno" @@ -273,142 +273,142 @@ msgstr "Diskuze" msgid "Search in %s directory" msgstr "Hledat v adresáři %s" -#: ../gtk/friendlist.c:975 +#: ../gtk/friendlist.c:976 #, c-format msgid "Edit contact '%s'" msgstr "Upravit kontakt „%s“" -#: ../gtk/friendlist.c:976 +#: ../gtk/friendlist.c:977 #, c-format msgid "Delete contact '%s'" msgstr "Odstranit kontakt „%s“" -#: ../gtk/friendlist.c:977 +#: ../gtk/friendlist.c:978 #, c-format msgid "Delete chat history of '%s'" msgstr "Odstranit historii diskuze u kontaktu „%s“" -#: ../gtk/friendlist.c:1028 +#: ../gtk/friendlist.c:1029 #, c-format msgid "Add new contact from %s directory" msgstr "Přidat nový kontakt z adresáře %s" -#: ../gtk/propertybox.c:556 +#: ../gtk/propertybox.c:558 msgid "Rate (Hz)" msgstr "Kmitočet (Hz)" -#: ../gtk/propertybox.c:562 +#: ../gtk/propertybox.c:564 msgid "Status" msgstr "Stav" -#: ../gtk/propertybox.c:568 +#: ../gtk/propertybox.c:570 #, fuzzy msgid "IP Bitrate (kbit/s)" msgstr "Min. rychlost (kb/s)" -#: ../gtk/propertybox.c:575 +#: ../gtk/propertybox.c:577 msgid "Parameters" msgstr "Parametry" -#: ../gtk/propertybox.c:618 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:763 msgid "Enabled" msgstr "Povoleno" -#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:622 ../gtk/propertybox.c:763 msgid "Disabled" msgstr "Zakázáno" -#: ../gtk/propertybox.c:807 +#: ../gtk/propertybox.c:809 msgid "Account" msgstr "Účet" -#: ../gtk/propertybox.c:1061 +#: ../gtk/propertybox.c:1063 msgid "English" msgstr "angličtina" -#: ../gtk/propertybox.c:1062 +#: ../gtk/propertybox.c:1064 msgid "French" msgstr "francouzština" -#: ../gtk/propertybox.c:1063 +#: ../gtk/propertybox.c:1065 msgid "Swedish" msgstr "švédština" -#: ../gtk/propertybox.c:1064 +#: ../gtk/propertybox.c:1066 msgid "Italian" msgstr "italština" -#: ../gtk/propertybox.c:1065 +#: ../gtk/propertybox.c:1067 msgid "Spanish" msgstr "španělština" -#: ../gtk/propertybox.c:1066 +#: ../gtk/propertybox.c:1068 msgid "Brazilian Portugese" msgstr "brazilská portugalština" -#: ../gtk/propertybox.c:1067 +#: ../gtk/propertybox.c:1069 msgid "Polish" msgstr "polština" -#: ../gtk/propertybox.c:1068 +#: ../gtk/propertybox.c:1070 msgid "German" msgstr "němčina" -#: ../gtk/propertybox.c:1069 +#: ../gtk/propertybox.c:1071 msgid "Russian" msgstr "ruština" -#: ../gtk/propertybox.c:1070 +#: ../gtk/propertybox.c:1072 msgid "Japanese" msgstr "japonština" -#: ../gtk/propertybox.c:1071 +#: ../gtk/propertybox.c:1073 msgid "Dutch" msgstr "dánština" -#: ../gtk/propertybox.c:1072 +#: ../gtk/propertybox.c:1074 msgid "Hungarian" msgstr "maďarština" -#: ../gtk/propertybox.c:1073 +#: ../gtk/propertybox.c:1075 msgid "Czech" msgstr "čeština" -#: ../gtk/propertybox.c:1074 +#: ../gtk/propertybox.c:1076 msgid "Chinese" msgstr "čínština" -#: ../gtk/propertybox.c:1075 +#: ../gtk/propertybox.c:1077 msgid "Traditional Chinese" msgstr "tradiční čínština" -#: ../gtk/propertybox.c:1076 +#: ../gtk/propertybox.c:1078 msgid "Norwegian" msgstr "norština" -#: ../gtk/propertybox.c:1077 +#: ../gtk/propertybox.c:1079 msgid "Hebrew" msgstr "hebrejština" -#: ../gtk/propertybox.c:1078 +#: ../gtk/propertybox.c:1080 msgid "Serbian" msgstr "srbština" -#: ../gtk/propertybox.c:1145 +#: ../gtk/propertybox.c:1147 msgid "" "You need to restart linphone for the new language selection to take effect." msgstr "Aby se projevil výběr nového jazyka, je nutné znovu spustit linphone." # Media encryption type: -#: ../gtk/propertybox.c:1223 +#: ../gtk/propertybox.c:1225 msgid "None" msgstr "Žádné" -#: ../gtk/propertybox.c:1227 +#: ../gtk/propertybox.c:1229 msgid "SRTP" msgstr "SRTP" -#: ../gtk/propertybox.c:1233 +#: ../gtk/propertybox.c:1235 msgid "ZRTP" msgstr "ZRTP" @@ -481,55 +481,59 @@ msgstr "" msgid "Enter your linphone.org username" msgstr "Zadejte uživatelské jméno na linphone.org" -#: ../gtk/setupwizard.c:96 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 +#: ../gtk/setupwizard.c:102 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 msgid "Username:" msgstr "Uživatelské jméno:" -#: ../gtk/setupwizard.c:98 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 +#: ../gtk/setupwizard.c:104 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 msgid "Password:" msgstr "Heslo:" -#: ../gtk/setupwizard.c:118 +#: ../gtk/setupwizard.c:124 msgid "Enter your account informations" msgstr "Zadejte údaje o vašem účtu" -#: ../gtk/setupwizard.c:125 +#: ../gtk/setupwizard.c:140 msgid "Username*" msgstr "Uživatelské jméno*" -#: ../gtk/setupwizard.c:126 +#: ../gtk/setupwizard.c:141 msgid "Password*" msgstr "Heslo*" -#: ../gtk/setupwizard.c:129 +#: ../gtk/setupwizard.c:144 msgid "Domain*" msgstr "Doména*" -#: ../gtk/setupwizard.c:130 +#: ../gtk/setupwizard.c:145 msgid "Proxy" msgstr "Proxy" -#: ../gtk/setupwizard.c:302 +#: ../gtk/setupwizard.c:317 msgid "(*) Required fields" msgstr "(*) Povinné položky" -#: ../gtk/setupwizard.c:303 +#: ../gtk/setupwizard.c:318 msgid "Username: (*)" msgstr "Uživatelské jméno: (*)" -#: ../gtk/setupwizard.c:305 +#: ../gtk/setupwizard.c:320 msgid "Password: (*)" msgstr "Heslo: (*)" -#: ../gtk/setupwizard.c:307 +#: ../gtk/setupwizard.c:322 msgid "Email: (*)" msgstr "E-mail: (*)" -#: ../gtk/setupwizard.c:309 +#: ../gtk/setupwizard.c:324 msgid "Confirm your password: (*)" msgstr "Potvrďte heslo: (*)" -#: ../gtk/setupwizard.c:373 +#: ../gtk/setupwizard.c:338 +msgid "Keep me informed with linphone updates" +msgstr "" + +#: ../gtk/setupwizard.c:394 msgid "" "Error, account not validated, username already used or server unreachable.\n" "Please go back and try again." @@ -538,11 +542,11 @@ msgstr "" "není dostupný).\n" "Prosím, vraťte se a zkoste to znovu." -#: ../gtk/setupwizard.c:384 +#: ../gtk/setupwizard.c:405 msgid "Thank you. Your account is now configured and ready for use." msgstr "Děkujeme vám. Váš účet je nyní nastaven a připraven k použití." -#: ../gtk/setupwizard.c:392 +#: ../gtk/setupwizard.c:413 msgid "" "Please validate your account by clicking on the link we just sent you by " "email.\n" @@ -552,40 +556,40 @@ msgstr "" "zaslali e-mailem.\n" "Pak se sem vraťte a stiskněte tlačítko Další." -#: ../gtk/setupwizard.c:564 +#: ../gtk/setupwizard.c:600 #, fuzzy msgid "SIP account configuration assistant" msgstr "Průvodce nastavením účtu" -#: ../gtk/setupwizard.c:582 +#: ../gtk/setupwizard.c:618 msgid "Welcome to the account setup assistant" msgstr "Vítejte v průvodci nastavení účtu" -#: ../gtk/setupwizard.c:587 +#: ../gtk/setupwizard.c:623 msgid "Account setup assistant" msgstr "Průvodce nastavením účtu" -#: ../gtk/setupwizard.c:593 +#: ../gtk/setupwizard.c:629 msgid "Configure your account (step 1/1)" msgstr "Nastavit účet (krok 1/1)" -#: ../gtk/setupwizard.c:598 +#: ../gtk/setupwizard.c:634 msgid "Enter your sip username (step 1/1)" msgstr "Zadejte vaše sipové uživatelské jméno (krok 1/1)" -#: ../gtk/setupwizard.c:602 +#: ../gtk/setupwizard.c:638 msgid "Enter account information (step 1/2)" msgstr "Zadejte údaje o účtu (krok 1/2)" -#: ../gtk/setupwizard.c:611 +#: ../gtk/setupwizard.c:647 msgid "Validation (step 2/2)" msgstr "Ověření (krok 2/2)" -#: ../gtk/setupwizard.c:616 +#: ../gtk/setupwizard.c:652 msgid "Error" msgstr "Chyba" -#: ../gtk/setupwizard.c:620 ../gtk/audio_assistant.c:519 +#: ../gtk/setupwizard.c:656 ../gtk/audio_assistant.c:527 msgid "Terminating" msgstr "Ukončuje se" @@ -651,7 +655,7 @@ msgstr "UPnP selhalo" msgid "Direct or through server" msgstr "Přímé nebo skrze server" -#: ../gtk/incall_view.c:266 ../gtk/incall_view.c:276 +#: ../gtk/incall_view.c:267 ../gtk/incall_view.c:279 #, c-format msgid "" "download: %f\n" @@ -660,115 +664,115 @@ msgstr "" "příchozí: %f\n" "odchozí: %f (kb/s)" -#: ../gtk/incall_view.c:271 ../gtk/incall_view.c:272 +#: ../gtk/incall_view.c:272 ../gtk/incall_view.c:274 #, c-format -msgid "%ix%i" +msgid "%ix%i @ %f fps" msgstr "" -#: ../gtk/incall_view.c:301 +#: ../gtk/incall_view.c:304 #, c-format msgid "%.3f seconds" msgstr "%.3f sekund" -#: ../gtk/incall_view.c:399 ../gtk/main.ui.h:12 +#: ../gtk/incall_view.c:407 ../gtk/main.ui.h:12 msgid "Hang up" msgstr "Zavěsit" -#: ../gtk/incall_view.c:492 +#: ../gtk/incall_view.c:501 msgid "Calling..." msgstr "Volá se…" -#: ../gtk/incall_view.c:495 ../gtk/incall_view.c:698 +#: ../gtk/incall_view.c:504 ../gtk/incall_view.c:707 msgid "00::00::00" msgstr "00:00:00" -#: ../gtk/incall_view.c:506 +#: ../gtk/incall_view.c:515 msgid "Incoming call" msgstr "Příchozí hovor" -#: ../gtk/incall_view.c:543 +#: ../gtk/incall_view.c:552 msgid "good" msgstr "dobrá" -#: ../gtk/incall_view.c:545 +#: ../gtk/incall_view.c:554 msgid "average" msgstr "průměrná" -#: ../gtk/incall_view.c:547 +#: ../gtk/incall_view.c:556 msgid "poor" msgstr "slabá" -#: ../gtk/incall_view.c:549 +#: ../gtk/incall_view.c:558 msgid "very poor" msgstr "velmi slabá" -#: ../gtk/incall_view.c:551 +#: ../gtk/incall_view.c:560 msgid "too bad" msgstr "příliš špatná" -#: ../gtk/incall_view.c:552 ../gtk/incall_view.c:568 +#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:577 msgid "unavailable" msgstr "nedostupná" -#: ../gtk/incall_view.c:660 +#: ../gtk/incall_view.c:669 msgid "Secured by SRTP" msgstr "Zabezpečeno pomocí SRTP" -#: ../gtk/incall_view.c:666 +#: ../gtk/incall_view.c:675 #, c-format msgid "Secured by ZRTP - [auth token: %s]" msgstr "Zabezpečeno pomocí ZRTP – [ověřovací klíč: %s]" -#: ../gtk/incall_view.c:672 +#: ../gtk/incall_view.c:681 msgid "Set unverified" msgstr "Nastavit na neověřeno" -#: ../gtk/incall_view.c:672 ../gtk/main.ui.h:4 +#: ../gtk/incall_view.c:681 ../gtk/main.ui.h:4 msgid "Set verified" msgstr "Nastavit na ověřeno" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In conference" msgstr "Probíhá konference" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In call" msgstr "Probíhá hovor" -#: ../gtk/incall_view.c:729 +#: ../gtk/incall_view.c:738 msgid "Paused call" msgstr "Odložený hovor" -#: ../gtk/incall_view.c:742 +#: ../gtk/incall_view.c:751 #, c-format msgid "%02i::%02i::%02i" msgstr "%02i:%02i:%02i" -#: ../gtk/incall_view.c:760 +#: ../gtk/incall_view.c:772 msgid "Call ended." msgstr "Hovor skončil." -#: ../gtk/incall_view.c:791 +#: ../gtk/incall_view.c:803 msgid "Transfer in progress" msgstr "Probíhá přepojení" -#: ../gtk/incall_view.c:794 +#: ../gtk/incall_view.c:806 msgid "Transfer done." msgstr "Přepojení dokončeno." -#: ../gtk/incall_view.c:797 +#: ../gtk/incall_view.c:809 msgid "Transfer failed." msgstr "Přepojení selhalo." -#: ../gtk/incall_view.c:841 +#: ../gtk/incall_view.c:853 msgid "Resume" msgstr "Obnovit" -#: ../gtk/incall_view.c:848 ../gtk/main.ui.h:9 +#: ../gtk/incall_view.c:860 ../gtk/main.ui.h:9 msgid "Pause" msgstr "Odložit" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, c-format msgid "" "Recording into\n" @@ -777,7 +781,7 @@ msgstr "" "Nahrává se do\n" "%s %s" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 msgid "(Paused)" msgstr "(Odloženo)" @@ -812,7 +816,7 @@ msgstr "" msgid "Too loud" msgstr "" -#: ../gtk/audio_assistant.c:316 +#: ../gtk/audio_assistant.c:318 #, fuzzy msgid "" "Welcome !\n" @@ -821,60 +825,60 @@ msgstr "" "Vítejte!\n" "Tento průvodce vám pomůže používat sipový účet při vašich hovorech." -#: ../gtk/audio_assistant.c:326 +#: ../gtk/audio_assistant.c:328 #, fuzzy msgid "Capture device" msgstr "Zařízení pro nahrávání:" -#: ../gtk/audio_assistant.c:327 +#: ../gtk/audio_assistant.c:329 #, fuzzy msgid "Recorded volume" msgstr "Zdroj nahrávání:" -#: ../gtk/audio_assistant.c:331 +#: ../gtk/audio_assistant.c:333 msgid "No voice" msgstr "" -#: ../gtk/audio_assistant.c:367 +#: ../gtk/audio_assistant.c:369 #, fuzzy msgid "Playback device" msgstr "Zařízení pro přehrávání:" -#: ../gtk/audio_assistant.c:368 +#: ../gtk/audio_assistant.c:370 msgid "Play three beeps" msgstr "" -#: ../gtk/audio_assistant.c:400 +#: ../gtk/audio_assistant.c:403 msgid "Press the record button and say some words" msgstr "" -#: ../gtk/audio_assistant.c:401 +#: ../gtk/audio_assistant.c:404 msgid "Listen to your record voice" msgstr "" -#: ../gtk/audio_assistant.c:430 +#: ../gtk/audio_assistant.c:433 msgid "Let's start Linphone now" msgstr "" -#: ../gtk/audio_assistant.c:488 +#: ../gtk/audio_assistant.c:496 #, fuzzy msgid "Audio Assistant" msgstr "Průvodce" -#: ../gtk/audio_assistant.c:498 ../gtk/main.ui.h:31 +#: ../gtk/audio_assistant.c:506 ../gtk/main.ui.h:31 #, fuzzy msgid "Audio assistant" msgstr "Průvodce účtem" -#: ../gtk/audio_assistant.c:503 +#: ../gtk/audio_assistant.c:511 msgid "Mic Gain calibration" msgstr "" -#: ../gtk/audio_assistant.c:509 +#: ../gtk/audio_assistant.c:517 msgid "Speaker volume calibration" msgstr "" -#: ../gtk/audio_assistant.c:514 +#: ../gtk/audio_assistant.c:522 msgid "Record and Play" msgstr "" @@ -1820,96 +1824,65 @@ msgstr "Připojuje se…" msgid "Please wait while fetching configuration from server..." msgstr "" -#: ../coreapi/linphonecore.c:242 -msgid "aborted" -msgstr "přerušen" - -#: ../coreapi/linphonecore.c:245 -msgid "completed" -msgstr "dokončen" - -#: ../coreapi/linphonecore.c:248 -msgid "missed" -msgstr "promeškán" - -#: ../coreapi/linphonecore.c:253 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" -"%s v %s\n" -"Od: %s\n" -"Pro: %s\n" -"Stav: %s\n" -"Délka: %i min %i s\n" - -#: ../coreapi/linphonecore.c:254 -msgid "Outgoing call" -msgstr "Odchozí hovor" - -#: ../coreapi/linphonecore.c:1287 +#: ../coreapi/linphonecore.c:1034 msgid "Ready" msgstr "Připraven." -#: ../coreapi/linphonecore.c:2248 +#: ../coreapi/linphonecore.c:1967 #, fuzzy msgid "Configuring" msgstr "Potvrzení" -#: ../coreapi/linphonecore.c:2410 +#: ../coreapi/linphonecore.c:2133 msgid "Looking for telephone number destination..." msgstr "Vyhledává se umístění čísla…" -#: ../coreapi/linphonecore.c:2413 +#: ../coreapi/linphonecore.c:2136 msgid "Could not resolve this number." msgstr "Toto číslo nelze vyhledat." #. must be known at that time -#: ../coreapi/linphonecore.c:2695 +#: ../coreapi/linphonecore.c:2418 msgid "Contacting" msgstr "Navazuje se spojení" -#: ../coreapi/linphonecore.c:2702 +#: ../coreapi/linphonecore.c:2425 msgid "Could not call" msgstr "Nelze volat" -#: ../coreapi/linphonecore.c:2852 +#: ../coreapi/linphonecore.c:2576 msgid "Sorry, we have reached the maximum number of simultaneous calls" msgstr "Je nám líto, ale byl dosažen maximální počet současných hovorů." -#: ../coreapi/linphonecore.c:3022 +#: ../coreapi/linphonecore.c:2745 msgid "is contacting you" msgstr "vás volá" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid " and asked autoanswer." msgstr " a požaduje automatickou zvednutí." -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid "." msgstr "." -#: ../coreapi/linphonecore.c:3139 +#: ../coreapi/linphonecore.c:2865 msgid "Modifying call parameters..." msgstr "Upravují se parametry hovoru…" -#: ../coreapi/linphonecore.c:3469 +#: ../coreapi/linphonecore.c:3194 msgid "Connected." msgstr "Připojeno." -#: ../coreapi/linphonecore.c:3495 +#: ../coreapi/linphonecore.c:3220 msgid "Call aborted" msgstr "Hovor přerušen" -#: ../coreapi/linphonecore.c:3685 +#: ../coreapi/linphonecore.c:3412 msgid "Could not pause the call" msgstr "Hovor nebylo možné odložit" -#: ../coreapi/linphonecore.c:3690 +#: ../coreapi/linphonecore.c:3417 msgid "Pausing the current call..." msgstr "Současný hovor se odkládá…" @@ -1974,7 +1947,7 @@ msgstr "Délka" msgid "Unknown-bug" msgstr "Neznámá chyba" -#: ../coreapi/proxy.c:279 +#: ../coreapi/proxy.c:314 msgid "" "The sip proxy address you entered is invalid, it must start with \"sip:\" " "followed by a hostname." @@ -1982,7 +1955,7 @@ msgstr "" "Adresa SIP proxy, kterou jste zadali, není platná. Musí začínat na „sip:“ a " "pak musí následovat jméno stroje." -#: ../coreapi/proxy.c:285 +#: ../coreapi/proxy.c:320 msgid "" "The sip identity you entered is invalid.\n" "It should look like sip:username@proxydomain, such as sip:alice@example.net" @@ -1990,124 +1963,124 @@ msgstr "" "SIP identita, kterou jste zadali, není platná.\n" "Měla by mít tvar sip:uživatel@proxydoména, například sip:alice@example.net" -#: ../coreapi/proxy.c:1299 +#: ../coreapi/proxy.c:1369 #, c-format msgid "Could not login as %s" msgstr "Nelze se přihlásit jako %s" -#: ../coreapi/callbacks.c:354 +#: ../coreapi/callbacks.c:355 msgid "Remote ringing." msgstr "Vyzvání na druhé straně." -#: ../coreapi/callbacks.c:370 +#: ../coreapi/callbacks.c:373 msgid "Remote ringing..." msgstr "Vyzvání na druhé straně…" -#: ../coreapi/callbacks.c:381 +#: ../coreapi/callbacks.c:384 msgid "Early media." msgstr "Časná média." -#: ../coreapi/callbacks.c:432 +#: ../coreapi/callbacks.c:435 #, c-format msgid "Call with %s is paused." msgstr "Hovor s %s je odložen." -#: ../coreapi/callbacks.c:445 +#: ../coreapi/callbacks.c:448 #, c-format msgid "Call answered by %s - on hold." msgstr "Hovor přijat kým: %s – odložen." -#: ../coreapi/callbacks.c:456 +#: ../coreapi/callbacks.c:459 msgid "Call resumed." msgstr "Hovor obnoven." -#: ../coreapi/callbacks.c:461 +#: ../coreapi/callbacks.c:464 #, c-format msgid "Call answered by %s." msgstr "Hovor přijat kým: %s." -#: ../coreapi/callbacks.c:480 +#: ../coreapi/callbacks.c:483 msgid "Incompatible, check codecs or security settings..." msgstr "Není slučitelné. Zkontrolujte nastavení kodeků a zabezpečení…" -#: ../coreapi/callbacks.c:531 +#: ../coreapi/callbacks.c:512 msgid "We have been resumed." msgstr "Byli jsme obnoveni." -#: ../coreapi/callbacks.c:541 +#: ../coreapi/callbacks.c:521 msgid "We are paused by other party." msgstr "Byli jsme odloženi protistranou." -#: ../coreapi/callbacks.c:558 +#: ../coreapi/callbacks.c:556 msgid "Call is updated by remote." msgstr "Hovor byl aktualizován protistranou." -#: ../coreapi/callbacks.c:637 +#: ../coreapi/callbacks.c:658 msgid "Call terminated." msgstr "Hovor ukončen." -#: ../coreapi/callbacks.c:666 +#: ../coreapi/callbacks.c:687 msgid "User is busy." msgstr "Uživatel je zaneprázdněn." -#: ../coreapi/callbacks.c:667 +#: ../coreapi/callbacks.c:688 msgid "User is temporarily unavailable." msgstr "Uživatel je dočasně nedostupný." #. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:669 +#: ../coreapi/callbacks.c:690 msgid "User does not want to be disturbed." msgstr "Uživatel si nepřeje být rušen." -#: ../coreapi/callbacks.c:670 +#: ../coreapi/callbacks.c:691 msgid "Call declined." msgstr "Volání odmítnuto." -#: ../coreapi/callbacks.c:685 +#: ../coreapi/callbacks.c:706 msgid "Request timeout." msgstr "" -#: ../coreapi/callbacks.c:716 +#: ../coreapi/callbacks.c:737 msgid "Redirected" msgstr "Přesměrováno" -#: ../coreapi/callbacks.c:766 +#: ../coreapi/callbacks.c:787 msgid "Incompatible media parameters." msgstr "Neslučitelné parametry médií." -#: ../coreapi/callbacks.c:777 +#: ../coreapi/callbacks.c:798 msgid "Call failed." msgstr "Volání se nezdařilo." -#: ../coreapi/callbacks.c:852 +#: ../coreapi/callbacks.c:878 #, c-format msgid "Registration on %s successful." msgstr "Registrace na %s byla úspěšná." -#: ../coreapi/callbacks.c:853 +#: ../coreapi/callbacks.c:879 #, c-format msgid "Unregistration on %s done." msgstr "Odregistrování z %s hotovo." -#: ../coreapi/callbacks.c:875 +#: ../coreapi/callbacks.c:897 msgid "no response timeout" msgstr "odpověď nedorazila včas" -#: ../coreapi/callbacks.c:878 +#: ../coreapi/callbacks.c:900 #, c-format msgid "Registration on %s failed: %s" msgstr "Registrace na %s selhala: %s" -#: ../coreapi/callbacks.c:885 +#: ../coreapi/callbacks.c:907 msgid "Service unavailable, retrying" msgstr "" -#: ../coreapi/linphonecall.c:175 +#: ../coreapi/linphonecall.c:177 #, c-format msgid "Authentication token is %s" msgstr "Klíč k ověření totožnosti je %s" -#: ../coreapi/linphonecall.c:2994 +#: ../coreapi/linphonecall.c:2932 #, c-format msgid "You have missed %i call." msgid_plural "You have missed %i calls." @@ -2115,6 +2088,31 @@ msgstr[0] "Máte %i zmeškaný hovor." msgstr[1] "Máte %i zmeškané hovory." msgstr[2] "Máte %i zmeškaných hovorů." +#~ msgid "aborted" +#~ msgstr "přerušen" + +#~ msgid "completed" +#~ msgstr "dokončen" + +#~ msgid "missed" +#~ msgstr "promeškán" + +#~ msgid "" +#~ "%s at %s\n" +#~ "From: %s\n" +#~ "To: %s\n" +#~ "Status: %s\n" +#~ "Duration: %i mn %i sec\n" +#~ msgstr "" +#~ "%s v %s\n" +#~ "Od: %s\n" +#~ "Pro: %s\n" +#~ "Stav: %s\n" +#~ "Délka: %i min %i s\n" + +#~ msgid "Outgoing call" +#~ msgstr "Odchozí hovor" + #~ msgid "No response." #~ msgstr "Žádná odpověď." diff --git a/po/de.po b/po/de.po index baec9ff8d..81e18df10 100644 --- a/po/de.po +++ b/po/de.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: linphone 0.7.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-01 21:24+0200\n" +"POT-Creation-Date: 2014-09-15 09:24+0200\n" "PO-Revision-Date: 2012-11-07 19:27+0100\n" "Last-Translator: Gerhard Stengel \n" "Language-Team: German \n" @@ -17,12 +17,12 @@ msgstr "" "X-Generator: Lokalize 1.5\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:973 +#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:974 #, c-format msgid "Call %s" msgstr "„%s“ anrufen" -#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:974 +#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:975 #, c-format msgid "Send text to %s" msgstr "Text zu „%s“ schicken" @@ -32,42 +32,42 @@ msgstr "Text zu „%s“ schicken" msgid "Recent calls (%i)" msgstr "Im Gespräch" -#: ../gtk/calllogs.c:312 +#: ../gtk/calllogs.c:314 msgid "n/a" msgstr "nicht verfügbar" -#: ../gtk/calllogs.c:315 +#: ../gtk/calllogs.c:317 msgid "Aborted" msgstr "Abgebrochen" -#: ../gtk/calllogs.c:318 +#: ../gtk/calllogs.c:320 msgid "Missed" msgstr "Entgangen" -#: ../gtk/calllogs.c:321 +#: ../gtk/calllogs.c:323 msgid "Declined" msgstr "Abgewiesen" -#: ../gtk/calllogs.c:327 +#: ../gtk/calllogs.c:329 #, c-format msgid "%i minute" msgid_plural "%i minutes" msgstr[0] "%i Minute" msgstr[1] "%i Minuten" -#: ../gtk/calllogs.c:330 +#: ../gtk/calllogs.c:332 #, c-format msgid "%i second" msgid_plural "%i seconds" msgstr[0] "%i Sekunde" msgstr[1] "%i Sekunden" -#: ../gtk/calllogs.c:333 ../gtk/calllogs.c:339 +#: ../gtk/calllogs.c:335 ../gtk/calllogs.c:341 #, c-format msgid "%s\t%s" msgstr "" -#: ../gtk/calllogs.c:335 +#: ../gtk/calllogs.c:337 #, fuzzy, c-format msgid "" "%s\tQuality: %s\n" @@ -76,7 +76,7 @@ msgstr "" "%s\t%s\tQualität: %s\n" "%s\t%s %s\t" -#: ../gtk/calllogs.c:341 +#: ../gtk/calllogs.c:343 #, c-format msgid "" "%s\t\n" @@ -96,7 +96,7 @@ msgstr "Eigenes Telefon" msgid "Couldn't find pixmap file: %s" msgstr "Pixmapdatei %s kann nicht gefunden werden." -#: ../gtk/chat.c:363 ../gtk/friendlist.c:923 +#: ../gtk/chat.c:364 ../gtk/friendlist.c:924 msgid "Invalid sip contact !" msgstr "Ungültiger SIP-Kontakt!" @@ -149,7 +149,7 @@ msgstr "Konto-Einrichtungsassistent" msgid "Call with %s" msgstr "Im Gespräch mit %s" -#: ../gtk/main.c:1171 +#: ../gtk/main.c:1183 #, c-format msgid "" "%s would like to add you to his contact list.\n" @@ -162,7 +162,7 @@ msgstr "" "Ihrer Kontaktliste hinzufügen?\n" "Wenn Sie mit Nein antworten, wird diese Person vorläufig blockiert." -#: ../gtk/main.c:1248 +#: ../gtk/main.c:1260 #, fuzzy, c-format msgid "" "Please enter your password for username %s\n" @@ -171,59 +171,59 @@ msgstr "" "Geben Sie bitte Ihr Passwort für den Benutzernamen %s\n" " auf der Domäne %s ein:" -#: ../gtk/main.c:1364 +#: ../gtk/main.c:1376 msgid "Call error" msgstr "Anruf fehlgeschlagen" -#: ../gtk/main.c:1367 ../coreapi/linphonecore.c:3515 +#: ../gtk/main.c:1379 ../coreapi/linphonecore.c:3240 msgid "Call ended" msgstr "Anruf beendet" -#: ../gtk/main.c:1370 ../coreapi/linphonecore.c:254 +#: ../gtk/main.c:1382 msgid "Incoming call" msgstr "Eingehender Anruf" -#: ../gtk/main.c:1372 ../gtk/incall_view.c:513 ../gtk/main.ui.h:5 +#: ../gtk/main.c:1384 ../gtk/incall_view.c:522 ../gtk/main.ui.h:5 msgid "Answer" msgstr "Annehmen" -#: ../gtk/main.c:1374 ../gtk/main.ui.h:6 +#: ../gtk/main.c:1386 ../gtk/main.ui.h:6 msgid "Decline" msgstr "Abweisen" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 msgid "Call paused" msgstr "Anruf wird gehalten" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, c-format msgid "by %s" msgstr "von %s" -#: ../gtk/main.c:1447 +#: ../gtk/main.c:1459 #, c-format msgid "%s proposed to start video. Do you accept ?" msgstr "%s schlägt vor, eine Videoübertragung zu starten. Nehmen Sie an?" -#: ../gtk/main.c:1609 +#: ../gtk/main.c:1621 msgid "Website link" msgstr "Website-Verknüpfung" -#: ../gtk/main.c:1658 +#: ../gtk/main.c:1670 msgid "Linphone - a video internet phone" msgstr "Linphone - ein Internet-Video-Telefon" -#: ../gtk/main.c:1750 +#: ../gtk/main.c:1762 #, c-format msgid "%s (Default)" msgstr "%s (Vorgabe)" -#: ../gtk/main.c:2086 ../coreapi/callbacks.c:927 +#: ../gtk/main.c:2099 ../coreapi/callbacks.c:949 #, c-format msgid "We are transferred to %s" msgstr "Vermittlung nach %s" -#: ../gtk/main.c:2096 +#: ../gtk/main.c:2109 msgid "" "No sound cards have been detected on this computer.\n" "You won't be able to send or receive audio calls." @@ -231,7 +231,7 @@ msgstr "" "Auf diesem Rechner können keine Soundkarten gefunden werden.\n" "Sie können keine Audio-Anrufe tätigen oder entgegennehmen." -#: ../gtk/main.c:2237 +#: ../gtk/main.c:2250 msgid "A free SIP video-phone" msgstr "Ein freies SIP-Video-Telefon" @@ -243,7 +243,7 @@ msgstr "Zum Adressbuch hinzufügen" msgid "Presence status" msgstr "Anwesenheitsstatus" -#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:550 ../gtk/contact.ui.h:1 +#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:552 ../gtk/contact.ui.h:1 msgid "Name" msgstr "Name" @@ -261,143 +261,143 @@ msgstr "Chat Raum" msgid "Search in %s directory" msgstr "Im %s-Verzeichnis suchen" -#: ../gtk/friendlist.c:975 +#: ../gtk/friendlist.c:976 #, c-format msgid "Edit contact '%s'" msgstr "Kontakt „%s“ bearbeiten" -#: ../gtk/friendlist.c:976 +#: ../gtk/friendlist.c:977 #, c-format msgid "Delete contact '%s'" msgstr "Kontakt „%s“ löschen" -#: ../gtk/friendlist.c:977 +#: ../gtk/friendlist.c:978 #, fuzzy, c-format msgid "Delete chat history of '%s'" msgstr "Kontakt „%s“ löschen" -#: ../gtk/friendlist.c:1028 +#: ../gtk/friendlist.c:1029 #, c-format msgid "Add new contact from %s directory" msgstr "Einen neuen Kontakt aus dem %s-Verzeichnis hinzufügen" -#: ../gtk/propertybox.c:556 +#: ../gtk/propertybox.c:558 msgid "Rate (Hz)" msgstr "Rate (Hz)" -#: ../gtk/propertybox.c:562 +#: ../gtk/propertybox.c:564 msgid "Status" msgstr "Status" -#: ../gtk/propertybox.c:568 +#: ../gtk/propertybox.c:570 #, fuzzy msgid "IP Bitrate (kbit/s)" msgstr "Min. Bitrate (kbit/s)" -#: ../gtk/propertybox.c:575 +#: ../gtk/propertybox.c:577 msgid "Parameters" msgstr "Parameter" -#: ../gtk/propertybox.c:618 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:763 msgid "Enabled" msgstr "Freigegeben" -#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:622 ../gtk/propertybox.c:763 msgid "Disabled" msgstr "Gesperrt" -#: ../gtk/propertybox.c:807 +#: ../gtk/propertybox.c:809 msgid "Account" msgstr "Konto" -#: ../gtk/propertybox.c:1061 +#: ../gtk/propertybox.c:1063 msgid "English" msgstr "Englisch" -#: ../gtk/propertybox.c:1062 +#: ../gtk/propertybox.c:1064 msgid "French" msgstr "Französisch" -#: ../gtk/propertybox.c:1063 +#: ../gtk/propertybox.c:1065 msgid "Swedish" msgstr "Schwedisch" -#: ../gtk/propertybox.c:1064 +#: ../gtk/propertybox.c:1066 msgid "Italian" msgstr "Italienisch" -#: ../gtk/propertybox.c:1065 +#: ../gtk/propertybox.c:1067 msgid "Spanish" msgstr "Spanisch" -#: ../gtk/propertybox.c:1066 +#: ../gtk/propertybox.c:1068 msgid "Brazilian Portugese" msgstr "Brasilianisches Portugiesisch" -#: ../gtk/propertybox.c:1067 +#: ../gtk/propertybox.c:1069 msgid "Polish" msgstr "Polnisch" -#: ../gtk/propertybox.c:1068 +#: ../gtk/propertybox.c:1070 msgid "German" msgstr "Deutsch" -#: ../gtk/propertybox.c:1069 +#: ../gtk/propertybox.c:1071 msgid "Russian" msgstr "Russisch" -#: ../gtk/propertybox.c:1070 +#: ../gtk/propertybox.c:1072 msgid "Japanese" msgstr "Japanisch" -#: ../gtk/propertybox.c:1071 +#: ../gtk/propertybox.c:1073 msgid "Dutch" msgstr "Niederländisch" -#: ../gtk/propertybox.c:1072 +#: ../gtk/propertybox.c:1074 msgid "Hungarian" msgstr "Ungarisch" -#: ../gtk/propertybox.c:1073 +#: ../gtk/propertybox.c:1075 msgid "Czech" msgstr "Tschechisch" -#: ../gtk/propertybox.c:1074 +#: ../gtk/propertybox.c:1076 msgid "Chinese" msgstr "Chinesisch" -#: ../gtk/propertybox.c:1075 +#: ../gtk/propertybox.c:1077 msgid "Traditional Chinese" msgstr "Traditionelles Chinesisch" -#: ../gtk/propertybox.c:1076 +#: ../gtk/propertybox.c:1078 msgid "Norwegian" msgstr "Norwegisch" -#: ../gtk/propertybox.c:1077 +#: ../gtk/propertybox.c:1079 msgid "Hebrew" msgstr "" -#: ../gtk/propertybox.c:1078 +#: ../gtk/propertybox.c:1080 msgid "Serbian" msgstr "" -#: ../gtk/propertybox.c:1145 +#: ../gtk/propertybox.c:1147 msgid "" "You need to restart linphone for the new language selection to take effect." msgstr "" "Linphone muss neu gestartet werden, damit die neue Spracheinstellung wirksam " "wird." -#: ../gtk/propertybox.c:1223 +#: ../gtk/propertybox.c:1225 msgid "None" msgstr "Keinen" -#: ../gtk/propertybox.c:1227 +#: ../gtk/propertybox.c:1229 msgid "SRTP" msgstr "" -#: ../gtk/propertybox.c:1233 +#: ../gtk/propertybox.c:1235 msgid "ZRTP" msgstr "" @@ -471,55 +471,59 @@ msgstr "" msgid "Enter your linphone.org username" msgstr "Geben Sie Ihren Benutzernamen bei linphone.org ein." -#: ../gtk/setupwizard.c:96 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 +#: ../gtk/setupwizard.c:102 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 msgid "Username:" msgstr "Benutzername:" -#: ../gtk/setupwizard.c:98 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 +#: ../gtk/setupwizard.c:104 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 msgid "Password:" msgstr "Passwort:" -#: ../gtk/setupwizard.c:118 +#: ../gtk/setupwizard.c:124 msgid "Enter your account informations" msgstr "Geben Sie Ihre Zugangsdaten ein." -#: ../gtk/setupwizard.c:125 +#: ../gtk/setupwizard.c:140 msgid "Username*" msgstr "Benutzername*" -#: ../gtk/setupwizard.c:126 +#: ../gtk/setupwizard.c:141 msgid "Password*" msgstr "Passwort*" -#: ../gtk/setupwizard.c:129 +#: ../gtk/setupwizard.c:144 msgid "Domain*" msgstr "Domäne*" -#: ../gtk/setupwizard.c:130 +#: ../gtk/setupwizard.c:145 msgid "Proxy" msgstr "Proxy" -#: ../gtk/setupwizard.c:302 +#: ../gtk/setupwizard.c:317 msgid "(*) Required fields" msgstr "(*) erforderliche Felder" -#: ../gtk/setupwizard.c:303 +#: ../gtk/setupwizard.c:318 msgid "Username: (*)" msgstr "Benutzername: (*)" -#: ../gtk/setupwizard.c:305 +#: ../gtk/setupwizard.c:320 msgid "Password: (*)" msgstr "Passwort: (*)" -#: ../gtk/setupwizard.c:307 +#: ../gtk/setupwizard.c:322 msgid "Email: (*)" msgstr "E-Mail: (*)" -#: ../gtk/setupwizard.c:309 +#: ../gtk/setupwizard.c:324 msgid "Confirm your password: (*)" msgstr "Bestätigen Sie Ihr Passwort: (*)" -#: ../gtk/setupwizard.c:373 +#: ../gtk/setupwizard.c:338 +msgid "Keep me informed with linphone updates" +msgstr "" + +#: ../gtk/setupwizard.c:394 msgid "" "Error, account not validated, username already used or server unreachable.\n" "Please go back and try again." @@ -528,12 +532,12 @@ msgstr "" "verwendet oder der Server ist unerreichbar.\n" "Bitte gehen Sie zurück und versuchen Sie es noch einmal." -#: ../gtk/setupwizard.c:384 +#: ../gtk/setupwizard.c:405 msgid "Thank you. Your account is now configured and ready for use." msgstr "" "Danke. Ihr Konto ist nun fertig eingerichtet und kann verwendet werden." -#: ../gtk/setupwizard.c:392 +#: ../gtk/setupwizard.c:413 msgid "" "Please validate your account by clicking on the link we just sent you by " "email.\n" @@ -543,40 +547,40 @@ msgstr "" "wir Ihnen soeben per E-Mail geschickt haben.\n" "Danach gehen Sie hierher zurück und drücken auf „Vor“." -#: ../gtk/setupwizard.c:564 +#: ../gtk/setupwizard.c:600 #, fuzzy msgid "SIP account configuration assistant" msgstr "Konto-Einrichtungsassistent" -#: ../gtk/setupwizard.c:582 +#: ../gtk/setupwizard.c:618 msgid "Welcome to the account setup assistant" msgstr "Willkommen zum Konto-Einrichtungsassistenten" -#: ../gtk/setupwizard.c:587 +#: ../gtk/setupwizard.c:623 msgid "Account setup assistant" msgstr "Konto-Einrichtungsassistent" -#: ../gtk/setupwizard.c:593 +#: ../gtk/setupwizard.c:629 msgid "Configure your account (step 1/1)" msgstr "Konto einrichten (Schritt 1/1)" -#: ../gtk/setupwizard.c:598 +#: ../gtk/setupwizard.c:634 msgid "Enter your sip username (step 1/1)" msgstr "Geben Sie Ihren SIP-Benutzernamen ein (Schritt 1/1)" -#: ../gtk/setupwizard.c:602 +#: ../gtk/setupwizard.c:638 msgid "Enter account information (step 1/2)" msgstr "Geben Sie Ihre Zugangsdaten ein (Schritt 1/2)" -#: ../gtk/setupwizard.c:611 +#: ../gtk/setupwizard.c:647 msgid "Validation (step 2/2)" msgstr "Bestätigung (Schritt 2/2)" -#: ../gtk/setupwizard.c:616 +#: ../gtk/setupwizard.c:652 msgid "Error" msgstr "Fehler" -#: ../gtk/setupwizard.c:620 ../gtk/audio_assistant.c:519 +#: ../gtk/setupwizard.c:656 ../gtk/audio_assistant.c:527 msgid "Terminating" msgstr "Fertigstellen" @@ -646,7 +650,7 @@ msgstr "ICE fehlgeschlagen" msgid "Direct or through server" msgstr "" -#: ../gtk/incall_view.c:266 ../gtk/incall_view.c:276 +#: ../gtk/incall_view.c:267 ../gtk/incall_view.c:279 #, c-format msgid "" "download: %f\n" @@ -655,122 +659,122 @@ msgstr "" "Herunterladen: %f\n" "Hochladen: %f (kbit/s)" -#: ../gtk/incall_view.c:271 ../gtk/incall_view.c:272 +#: ../gtk/incall_view.c:272 ../gtk/incall_view.c:274 #, c-format -msgid "%ix%i" +msgid "%ix%i @ %f fps" msgstr "" -#: ../gtk/incall_view.c:301 +#: ../gtk/incall_view.c:304 #, fuzzy, c-format msgid "%.3f seconds" msgstr "%i Sekunde" -#: ../gtk/incall_view.c:399 ../gtk/main.ui.h:12 +#: ../gtk/incall_view.c:407 ../gtk/main.ui.h:12 msgid "Hang up" msgstr "" -#: ../gtk/incall_view.c:492 +#: ../gtk/incall_view.c:501 msgid "Calling..." msgstr "Verbindungsaufbau..." -#: ../gtk/incall_view.c:495 ../gtk/incall_view.c:698 +#: ../gtk/incall_view.c:504 ../gtk/incall_view.c:707 msgid "00::00::00" msgstr "" -#: ../gtk/incall_view.c:506 +#: ../gtk/incall_view.c:515 msgid "Incoming call" msgstr "Eingehender Anruf" -#: ../gtk/incall_view.c:543 +#: ../gtk/incall_view.c:552 msgid "good" msgstr "gut" -#: ../gtk/incall_view.c:545 +#: ../gtk/incall_view.c:554 msgid "average" msgstr "durchschnittlich" -#: ../gtk/incall_view.c:547 +#: ../gtk/incall_view.c:556 msgid "poor" msgstr "schlecht" -#: ../gtk/incall_view.c:549 +#: ../gtk/incall_view.c:558 msgid "very poor" msgstr "sehr schlecht" -#: ../gtk/incall_view.c:551 +#: ../gtk/incall_view.c:560 msgid "too bad" msgstr "zu schlecht" -#: ../gtk/incall_view.c:552 ../gtk/incall_view.c:568 +#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:577 msgid "unavailable" msgstr "nicht verfügbar" -#: ../gtk/incall_view.c:660 +#: ../gtk/incall_view.c:669 msgid "Secured by SRTP" msgstr "Gesichert durch SRTP" -#: ../gtk/incall_view.c:666 +#: ../gtk/incall_view.c:675 #, c-format msgid "Secured by ZRTP - [auth token: %s]" msgstr "Gesichert durch ZRTP - [Auth.-Token: %s]" -#: ../gtk/incall_view.c:672 +#: ../gtk/incall_view.c:681 msgid "Set unverified" msgstr "Auf „Ungeprüft“ setzen" -#: ../gtk/incall_view.c:672 ../gtk/main.ui.h:4 +#: ../gtk/incall_view.c:681 ../gtk/main.ui.h:4 msgid "Set verified" msgstr "Auf „Geprüft“ setzen" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In conference" msgstr "In Konferenz" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In call" msgstr "Im Gespräch" -#: ../gtk/incall_view.c:729 +#: ../gtk/incall_view.c:738 msgid "Paused call" msgstr "Gehaltener Anruf" -#: ../gtk/incall_view.c:742 +#: ../gtk/incall_view.c:751 #, c-format msgid "%02i::%02i::%02i" msgstr "" -#: ../gtk/incall_view.c:760 +#: ../gtk/incall_view.c:772 msgid "Call ended." msgstr "Anruf beendet." -#: ../gtk/incall_view.c:791 +#: ../gtk/incall_view.c:803 msgid "Transfer in progress" msgstr "Vermittlung läuft" -#: ../gtk/incall_view.c:794 +#: ../gtk/incall_view.c:806 msgid "Transfer done." msgstr "Vermittlung abgeschlossen." -#: ../gtk/incall_view.c:797 +#: ../gtk/incall_view.c:809 msgid "Transfer failed." msgstr "Vermittlung fehlgeschlagen." -#: ../gtk/incall_view.c:841 +#: ../gtk/incall_view.c:853 msgid "Resume" msgstr "Fortsetzen" -#: ../gtk/incall_view.c:848 ../gtk/main.ui.h:9 +#: ../gtk/incall_view.c:860 ../gtk/main.ui.h:9 msgid "Pause" msgstr "Halten" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, c-format msgid "" "Recording into\n" "%s %s" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, fuzzy msgid "(Paused)" msgstr "Halten" @@ -806,7 +810,7 @@ msgstr "" msgid "Too loud" msgstr "" -#: ../gtk/audio_assistant.c:316 +#: ../gtk/audio_assistant.c:318 #, fuzzy msgid "" "Welcome !\n" @@ -816,60 +820,60 @@ msgstr "" "Dieser Assistent wird Ihnen dabei helfen, ein SIP-Konto für Ihre Anrufe zu " "verwenden." -#: ../gtk/audio_assistant.c:326 +#: ../gtk/audio_assistant.c:328 #, fuzzy msgid "Capture device" msgstr "Aufnahmegerät:" -#: ../gtk/audio_assistant.c:327 +#: ../gtk/audio_assistant.c:329 #, fuzzy msgid "Recorded volume" msgstr "Aufnahmequelle:" -#: ../gtk/audio_assistant.c:331 +#: ../gtk/audio_assistant.c:333 msgid "No voice" msgstr "" -#: ../gtk/audio_assistant.c:367 +#: ../gtk/audio_assistant.c:369 #, fuzzy msgid "Playback device" msgstr "Wiedergabegerät:" -#: ../gtk/audio_assistant.c:368 +#: ../gtk/audio_assistant.c:370 msgid "Play three beeps" msgstr "" -#: ../gtk/audio_assistant.c:400 +#: ../gtk/audio_assistant.c:403 msgid "Press the record button and say some words" msgstr "" -#: ../gtk/audio_assistant.c:401 +#: ../gtk/audio_assistant.c:404 msgid "Listen to your record voice" msgstr "" -#: ../gtk/audio_assistant.c:430 +#: ../gtk/audio_assistant.c:433 msgid "Let's start Linphone now" msgstr "" -#: ../gtk/audio_assistant.c:488 +#: ../gtk/audio_assistant.c:496 #, fuzzy msgid "Audio Assistant" msgstr "Konto-Einrichtungsassistent" -#: ../gtk/audio_assistant.c:498 ../gtk/main.ui.h:31 +#: ../gtk/audio_assistant.c:506 ../gtk/main.ui.h:31 #, fuzzy msgid "Audio assistant" msgstr "Konto-Einrichtungsassistent" -#: ../gtk/audio_assistant.c:503 +#: ../gtk/audio_assistant.c:511 msgid "Mic Gain calibration" msgstr "" -#: ../gtk/audio_assistant.c:509 +#: ../gtk/audio_assistant.c:517 msgid "Speaker volume calibration" msgstr "" -#: ../gtk/audio_assistant.c:514 +#: ../gtk/audio_assistant.c:522 msgid "Record and Play" msgstr "" @@ -1825,96 +1829,65 @@ msgstr "Verbinden..." msgid "Please wait while fetching configuration from server..." msgstr "" -#: ../coreapi/linphonecore.c:242 -msgid "aborted" -msgstr "abgebrochen" - -#: ../coreapi/linphonecore.c:245 -msgid "completed" -msgstr "beendet" - -#: ../coreapi/linphonecore.c:248 -msgid "missed" -msgstr "entgangen" - -#: ../coreapi/linphonecore.c:253 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" -"%s am %s\n" -"Von: %s\n" -"An: %s\n" -"Status: %s\n" -"Dauer: %i min %i sec\n" - -#: ../coreapi/linphonecore.c:254 -msgid "Outgoing call" -msgstr "Abgehender Anruf" - -#: ../coreapi/linphonecore.c:1287 +#: ../coreapi/linphonecore.c:1034 msgid "Ready" msgstr "Bereit" -#: ../coreapi/linphonecore.c:2248 +#: ../coreapi/linphonecore.c:1967 #, fuzzy msgid "Configuring" msgstr "Bestätigung" -#: ../coreapi/linphonecore.c:2410 +#: ../coreapi/linphonecore.c:2133 msgid "Looking for telephone number destination..." msgstr "Telefonnummernziel wird gesucht..." -#: ../coreapi/linphonecore.c:2413 +#: ../coreapi/linphonecore.c:2136 msgid "Could not resolve this number." msgstr "Diese Nummer kann nicht aufgelöst werden." #. must be known at that time -#: ../coreapi/linphonecore.c:2695 +#: ../coreapi/linphonecore.c:2418 msgid "Contacting" msgstr "Verbindungsaufbau" -#: ../coreapi/linphonecore.c:2702 +#: ../coreapi/linphonecore.c:2425 msgid "Could not call" msgstr "Anruf kann nicht getätigt werden." -#: ../coreapi/linphonecore.c:2852 +#: ../coreapi/linphonecore.c:2576 msgid "Sorry, we have reached the maximum number of simultaneous calls" msgstr "Die maximale Anzahl der gleichzeitigen Anrufe ist erreicht." -#: ../coreapi/linphonecore.c:3022 +#: ../coreapi/linphonecore.c:2745 msgid "is contacting you" msgstr "ruft Sie an" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid " and asked autoanswer." msgstr " und fragt nach automatischer Antwort." -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid "." msgstr "" -#: ../coreapi/linphonecore.c:3139 +#: ../coreapi/linphonecore.c:2865 msgid "Modifying call parameters..." msgstr "Die Anrufparameter werden verändert..." -#: ../coreapi/linphonecore.c:3469 +#: ../coreapi/linphonecore.c:3194 msgid "Connected." msgstr "Verbunden." -#: ../coreapi/linphonecore.c:3495 +#: ../coreapi/linphonecore.c:3220 msgid "Call aborted" msgstr "Anruf abgebrochen" -#: ../coreapi/linphonecore.c:3685 +#: ../coreapi/linphonecore.c:3412 msgid "Could not pause the call" msgstr "Anruf kann nicht gehalten werden" -#: ../coreapi/linphonecore.c:3690 +#: ../coreapi/linphonecore.c:3417 msgid "Pausing the current call..." msgstr "Aktueller Anruf wird gehalten..." @@ -1979,7 +1952,7 @@ msgstr "Dauer" msgid "Unknown-bug" msgstr "Unbekannter Fehler" -#: ../coreapi/proxy.c:279 +#: ../coreapi/proxy.c:314 msgid "" "The sip proxy address you entered is invalid, it must start with \"sip:\" " "followed by a hostname." @@ -1987,7 +1960,7 @@ msgstr "" "Die von Ihnen eingegebene SIP-Proxy-Adresse ist ungültig, sie muss mit " "„sip:“ gefolgt vom Hostnamen beginnen." -#: ../coreapi/proxy.c:285 +#: ../coreapi/proxy.c:320 msgid "" "The sip identity you entered is invalid.\n" "It should look like sip:username@proxydomain, such as sip:alice@example.net" @@ -1996,131 +1969,156 @@ msgstr "" "Sie sollte wie sip:benutzername@proxydomain aussehen, also z.B. sip:" "alice@beispiel.net" -#: ../coreapi/proxy.c:1299 +#: ../coreapi/proxy.c:1369 #, c-format msgid "Could not login as %s" msgstr "Anmeldung als %s fehlgeschlagen" -#: ../coreapi/callbacks.c:354 +#: ../coreapi/callbacks.c:355 msgid "Remote ringing." msgstr "Klingeln bei der Gegenseite." -#: ../coreapi/callbacks.c:370 +#: ../coreapi/callbacks.c:373 msgid "Remote ringing..." msgstr "Klingeln bei der Gegenseite..." -#: ../coreapi/callbacks.c:381 +#: ../coreapi/callbacks.c:384 msgid "Early media." msgstr "" -#: ../coreapi/callbacks.c:432 +#: ../coreapi/callbacks.c:435 #, c-format msgid "Call with %s is paused." msgstr "Anruf mit %s wird gehalten." -#: ../coreapi/callbacks.c:445 +#: ../coreapi/callbacks.c:448 #, c-format msgid "Call answered by %s - on hold." msgstr "Der von %s entgegengenommene Anruf wird gehalten." -#: ../coreapi/callbacks.c:456 +#: ../coreapi/callbacks.c:459 msgid "Call resumed." msgstr "Anruf fortgesetzt." -#: ../coreapi/callbacks.c:461 +#: ../coreapi/callbacks.c:464 #, c-format msgid "Call answered by %s." msgstr "Anruf wird von %s entgegengenommen." -#: ../coreapi/callbacks.c:480 +#: ../coreapi/callbacks.c:483 #, fuzzy msgid "Incompatible, check codecs or security settings..." msgstr "Inkompatibel, überprüfen Sie die Codecs..." -#: ../coreapi/callbacks.c:531 +#: ../coreapi/callbacks.c:512 msgid "We have been resumed." msgstr "Anruf wird fortgesetzt." -#: ../coreapi/callbacks.c:541 +#: ../coreapi/callbacks.c:521 msgid "We are paused by other party." msgstr "Anruf wird von der Gegenseite gehalten." -#: ../coreapi/callbacks.c:558 +#: ../coreapi/callbacks.c:556 msgid "Call is updated by remote." msgstr "Anruf ist von der Gegenseite aktualisiert worden." -#: ../coreapi/callbacks.c:637 +#: ../coreapi/callbacks.c:658 msgid "Call terminated." msgstr "Anruf beendet." -#: ../coreapi/callbacks.c:666 +#: ../coreapi/callbacks.c:687 msgid "User is busy." msgstr "Teilnehmer ist besetzt." -#: ../coreapi/callbacks.c:667 +#: ../coreapi/callbacks.c:688 msgid "User is temporarily unavailable." msgstr "Teilnehmer zur Zeit nicht verfügbar." #. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:669 +#: ../coreapi/callbacks.c:690 msgid "User does not want to be disturbed." msgstr "Teilnehmer möchte nicht gestört werden." -#: ../coreapi/callbacks.c:670 +#: ../coreapi/callbacks.c:691 msgid "Call declined." msgstr "Anruf abgewiesen" -#: ../coreapi/callbacks.c:685 +#: ../coreapi/callbacks.c:706 msgid "Request timeout." msgstr "" -#: ../coreapi/callbacks.c:716 +#: ../coreapi/callbacks.c:737 msgid "Redirected" msgstr "Umgeleitet" -#: ../coreapi/callbacks.c:766 +#: ../coreapi/callbacks.c:787 msgid "Incompatible media parameters." msgstr "Inkompatible Medienparameter." -#: ../coreapi/callbacks.c:777 +#: ../coreapi/callbacks.c:798 msgid "Call failed." msgstr "Anruf fehlgeschlagen." -#: ../coreapi/callbacks.c:852 +#: ../coreapi/callbacks.c:878 #, c-format msgid "Registration on %s successful." msgstr "Registrierung auf %s erfolgreich." -#: ../coreapi/callbacks.c:853 +#: ../coreapi/callbacks.c:879 #, c-format msgid "Unregistration on %s done." msgstr "Abmeldung von %s ist erfolgt." -#: ../coreapi/callbacks.c:875 +#: ../coreapi/callbacks.c:897 msgid "no response timeout" msgstr "Zeitüberschreitung bei der Antwort" -#: ../coreapi/callbacks.c:878 +#: ../coreapi/callbacks.c:900 #, c-format msgid "Registration on %s failed: %s" msgstr "Registrierung auf %s fehlgeschlagen: %s" -#: ../coreapi/callbacks.c:885 +#: ../coreapi/callbacks.c:907 msgid "Service unavailable, retrying" msgstr "" -#: ../coreapi/linphonecall.c:175 +#: ../coreapi/linphonecall.c:177 #, c-format msgid "Authentication token is %s" msgstr "Authentifizierungs-Token ist %s" -#: ../coreapi/linphonecall.c:2994 +#: ../coreapi/linphonecall.c:2932 #, c-format msgid "You have missed %i call." msgid_plural "You have missed %i calls." msgstr[0] "Sie haben %i Anruf in Abwesenheit." msgstr[1] "Sie haben %i Anrufe in Abwesenheit." +#~ msgid "aborted" +#~ msgstr "abgebrochen" + +#~ msgid "completed" +#~ msgstr "beendet" + +#~ msgid "missed" +#~ msgstr "entgangen" + +#~ msgid "" +#~ "%s at %s\n" +#~ "From: %s\n" +#~ "To: %s\n" +#~ "Status: %s\n" +#~ "Duration: %i mn %i sec\n" +#~ msgstr "" +#~ "%s am %s\n" +#~ "Von: %s\n" +#~ "An: %s\n" +#~ "Status: %s\n" +#~ "Dauer: %i min %i sec\n" + +#~ msgid "Outgoing call" +#~ msgstr "Abgehender Anruf" + #~ msgid "No response." #~ msgstr "Keine Antwort." diff --git a/po/es.po b/po/es.po index 37021a332..f58dac100 100644 --- a/po/es.po +++ b/po/es.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: Linphone 0.9.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-01 21:24+0200\n" +"POT-Creation-Date: 2014-09-15 09:24+0200\n" "PO-Revision-Date: 2012-12-06 15:54+0100\n" "Last-Translator: BERAUDO Guillaume \n" "Language-Team: es \n" @@ -15,12 +15,12 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:973 +#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:974 #, c-format msgid "Call %s" msgstr "Llamar a %s" -#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:974 +#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:975 #, c-format msgid "Send text to %s" msgstr "Enviar mensaje a %s" @@ -30,47 +30,47 @@ msgstr "Enviar mensaje a %s" msgid "Recent calls (%i)" msgstr "En llamada " -#: ../gtk/calllogs.c:312 +#: ../gtk/calllogs.c:314 msgid "n/a" msgstr "n/a" -#: ../gtk/calllogs.c:315 +#: ../gtk/calllogs.c:317 #, fuzzy msgid "Aborted" msgstr "abortada" -#: ../gtk/calllogs.c:318 +#: ../gtk/calllogs.c:320 #, fuzzy msgid "Missed" msgstr "perdida" -#: ../gtk/calllogs.c:321 +#: ../gtk/calllogs.c:323 #, fuzzy msgid "Declined" msgstr "Rechazar" -#: ../gtk/calllogs.c:327 +#: ../gtk/calllogs.c:329 #, c-format msgid "%i minute" msgid_plural "%i minutes" msgstr[0] "%i minuto" msgstr[1] "%i minutos" -#: ../gtk/calllogs.c:330 +#: ../gtk/calllogs.c:332 #, c-format msgid "%i second" msgid_plural "%i seconds" msgstr[0] "%i segundo" msgstr[1] "%i segundos" -#: ../gtk/calllogs.c:333 ../gtk/calllogs.c:339 +#: ../gtk/calllogs.c:335 ../gtk/calllogs.c:341 #, fuzzy, c-format msgid "%s\t%s" msgstr "" "%s\t%s\tCalidad: %s\n" "%s\t%s %s\t" -#: ../gtk/calllogs.c:335 +#: ../gtk/calllogs.c:337 #, fuzzy, c-format msgid "" "%s\tQuality: %s\n" @@ -79,7 +79,7 @@ msgstr "" "%s\t%s\tCalidad: %s\n" "%s\t%s %s\t" -#: ../gtk/calllogs.c:341 +#: ../gtk/calllogs.c:343 #, fuzzy, c-format msgid "" "%s\t\n" @@ -101,7 +101,7 @@ msgstr "Yo" msgid "Couldn't find pixmap file: %s" msgstr "No se pudo encontrar el archivo pixmap: %s" -#: ../gtk/chat.c:363 ../gtk/friendlist.c:923 +#: ../gtk/chat.c:364 ../gtk/friendlist.c:924 msgid "Invalid sip contact !" msgstr "¡Contacto SIP no válido!" @@ -153,7 +153,7 @@ msgstr "Asistente de configuración de cuenta" msgid "Call with %s" msgstr "Llamar con %s" -#: ../gtk/main.c:1171 +#: ../gtk/main.c:1183 #, c-format msgid "" "%s would like to add you to his contact list.\n" @@ -166,7 +166,7 @@ msgstr "" "contactos?\n" "Si responde no, esta persona será bloqueada temporalmente." -#: ../gtk/main.c:1248 +#: ../gtk/main.c:1260 #, fuzzy, c-format msgid "" "Please enter your password for username %s\n" @@ -175,63 +175,63 @@ msgstr "" "Por favor, introduzca la contraseña para el usuario %s\n" " en el dominio %s:" -#: ../gtk/main.c:1364 +#: ../gtk/main.c:1376 #, fuzzy msgid "Call error" msgstr "Error en la llamada." -#: ../gtk/main.c:1367 ../coreapi/linphonecore.c:3515 +#: ../gtk/main.c:1379 ../coreapi/linphonecore.c:3240 #, fuzzy msgid "Call ended" msgstr "Llamada terminada" -#: ../gtk/main.c:1370 ../coreapi/linphonecore.c:254 +#: ../gtk/main.c:1382 msgid "Incoming call" msgstr "Llamada entrante" -#: ../gtk/main.c:1372 ../gtk/incall_view.c:513 ../gtk/main.ui.h:5 +#: ../gtk/main.c:1384 ../gtk/incall_view.c:522 ../gtk/main.ui.h:5 msgid "Answer" msgstr "Contestar" -#: ../gtk/main.c:1374 ../gtk/main.ui.h:6 +#: ../gtk/main.c:1386 ../gtk/main.ui.h:6 #, fuzzy msgid "Decline" msgstr "Rechazar" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy msgid "Call paused" msgstr "Llamada en pausa" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy, c-format msgid "by %s" msgstr "Puertos" -#: ../gtk/main.c:1447 +#: ../gtk/main.c:1459 #, c-format msgid "%s proposed to start video. Do you accept ?" msgstr "" -#: ../gtk/main.c:1609 +#: ../gtk/main.c:1621 msgid "Website link" msgstr "Enlace a la Web" -#: ../gtk/main.c:1658 +#: ../gtk/main.c:1670 msgid "Linphone - a video internet phone" msgstr "Linphone - un video-teléfono a través de Internet" -#: ../gtk/main.c:1750 +#: ../gtk/main.c:1762 #, c-format msgid "%s (Default)" msgstr "%s (Opción predeterminada)" -#: ../gtk/main.c:2086 ../coreapi/callbacks.c:927 +#: ../gtk/main.c:2099 ../coreapi/callbacks.c:949 #, c-format msgid "We are transferred to %s" msgstr "Somos transferidos a %s" -#: ../gtk/main.c:2096 +#: ../gtk/main.c:2109 msgid "" "No sound cards have been detected on this computer.\n" "You won't be able to send or receive audio calls." @@ -239,7 +239,7 @@ msgstr "" "No se ha encontrado una tarjeta de sonido en este equipo.\n" "No será posible realizar o recibir llamadas de audio." -#: ../gtk/main.c:2237 +#: ../gtk/main.c:2250 msgid "A free SIP video-phone" msgstr "Un video-teléfono SIP gratuito" @@ -253,7 +253,7 @@ msgstr "Añadir a la agenda" msgid "Presence status" msgstr "Estado de Presencia" -#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:550 ../gtk/contact.ui.h:1 +#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:552 ../gtk/contact.ui.h:1 msgid "Name" msgstr "Nombre" @@ -271,142 +271,142 @@ msgstr "" msgid "Search in %s directory" msgstr "Buscar en el directorio %s" -#: ../gtk/friendlist.c:975 +#: ../gtk/friendlist.c:976 #, fuzzy, c-format msgid "Edit contact '%s'" msgstr "Editar contacto '%s'" -#: ../gtk/friendlist.c:976 +#: ../gtk/friendlist.c:977 #, c-format msgid "Delete contact '%s'" msgstr "Eliminar contacto '%s'" -#: ../gtk/friendlist.c:977 +#: ../gtk/friendlist.c:978 #, fuzzy, c-format msgid "Delete chat history of '%s'" msgstr "Eliminar contacto '%s'" -#: ../gtk/friendlist.c:1028 +#: ../gtk/friendlist.c:1029 #, c-format msgid "Add new contact from %s directory" msgstr "Añadir nuevo contacto desde el directorio %s" -#: ../gtk/propertybox.c:556 +#: ../gtk/propertybox.c:558 msgid "Rate (Hz)" msgstr "Frecuencia (Hz)" -#: ../gtk/propertybox.c:562 +#: ../gtk/propertybox.c:564 msgid "Status" msgstr "Estado" -#: ../gtk/propertybox.c:568 +#: ../gtk/propertybox.c:570 #, fuzzy msgid "IP Bitrate (kbit/s)" msgstr "Bitrate mínimo (kbit/s)" -#: ../gtk/propertybox.c:575 +#: ../gtk/propertybox.c:577 msgid "Parameters" msgstr "Parámetros" -#: ../gtk/propertybox.c:618 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:763 msgid "Enabled" msgstr "Activado" -#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:622 ../gtk/propertybox.c:763 msgid "Disabled" msgstr "Desactivado" -#: ../gtk/propertybox.c:807 +#: ../gtk/propertybox.c:809 msgid "Account" msgstr "Cuenta" -#: ../gtk/propertybox.c:1061 +#: ../gtk/propertybox.c:1063 msgid "English" msgstr "Inglés" -#: ../gtk/propertybox.c:1062 +#: ../gtk/propertybox.c:1064 msgid "French" msgstr "Francés" -#: ../gtk/propertybox.c:1063 +#: ../gtk/propertybox.c:1065 msgid "Swedish" msgstr "Sueco" -#: ../gtk/propertybox.c:1064 +#: ../gtk/propertybox.c:1066 msgid "Italian" msgstr "Italiano" -#: ../gtk/propertybox.c:1065 +#: ../gtk/propertybox.c:1067 msgid "Spanish" msgstr "Español" -#: ../gtk/propertybox.c:1066 +#: ../gtk/propertybox.c:1068 msgid "Brazilian Portugese" msgstr "Portugués de Brasil" -#: ../gtk/propertybox.c:1067 +#: ../gtk/propertybox.c:1069 msgid "Polish" msgstr "Polaco" -#: ../gtk/propertybox.c:1068 +#: ../gtk/propertybox.c:1070 msgid "German" msgstr "Alemán" -#: ../gtk/propertybox.c:1069 +#: ../gtk/propertybox.c:1071 msgid "Russian" msgstr "Ruso" -#: ../gtk/propertybox.c:1070 +#: ../gtk/propertybox.c:1072 msgid "Japanese" msgstr "Japonés" -#: ../gtk/propertybox.c:1071 +#: ../gtk/propertybox.c:1073 msgid "Dutch" msgstr "Holandés" -#: ../gtk/propertybox.c:1072 +#: ../gtk/propertybox.c:1074 msgid "Hungarian" msgstr "Húngaro" -#: ../gtk/propertybox.c:1073 +#: ../gtk/propertybox.c:1075 msgid "Czech" msgstr "Checo" -#: ../gtk/propertybox.c:1074 +#: ../gtk/propertybox.c:1076 msgid "Chinese" msgstr "Chino" -#: ../gtk/propertybox.c:1075 +#: ../gtk/propertybox.c:1077 msgid "Traditional Chinese" msgstr "Chino Tradicional" -#: ../gtk/propertybox.c:1076 +#: ../gtk/propertybox.c:1078 msgid "Norwegian" msgstr "Noruego" -#: ../gtk/propertybox.c:1077 +#: ../gtk/propertybox.c:1079 msgid "Hebrew" msgstr "" -#: ../gtk/propertybox.c:1078 +#: ../gtk/propertybox.c:1080 msgid "Serbian" msgstr "" -#: ../gtk/propertybox.c:1145 +#: ../gtk/propertybox.c:1147 msgid "" "You need to restart linphone for the new language selection to take effect." msgstr "Deberá reiniciar linphone para aplicar la nueva selección de lenguaje" -#: ../gtk/propertybox.c:1223 +#: ../gtk/propertybox.c:1225 #, fuzzy msgid "None" msgstr "Ninguno." -#: ../gtk/propertybox.c:1227 +#: ../gtk/propertybox.c:1229 msgid "SRTP" msgstr "SRTP" -#: ../gtk/propertybox.c:1233 +#: ../gtk/propertybox.c:1235 msgid "ZRTP" msgstr "ZRTP" @@ -484,112 +484,116 @@ msgstr "" msgid "Enter your linphone.org username" msgstr "" -#: ../gtk/setupwizard.c:96 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 +#: ../gtk/setupwizard.c:102 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 #, fuzzy msgid "Username:" msgstr "Nombre de usuario:" -#: ../gtk/setupwizard.c:98 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 +#: ../gtk/setupwizard.c:104 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 #, fuzzy msgid "Password:" msgstr "Contraseña:" -#: ../gtk/setupwizard.c:118 +#: ../gtk/setupwizard.c:124 msgid "Enter your account informations" msgstr "" -#: ../gtk/setupwizard.c:125 +#: ../gtk/setupwizard.c:140 #, fuzzy msgid "Username*" msgstr "Nombre de usuario" -#: ../gtk/setupwizard.c:126 +#: ../gtk/setupwizard.c:141 #, fuzzy msgid "Password*" msgstr "Contraseña:" -#: ../gtk/setupwizard.c:129 +#: ../gtk/setupwizard.c:144 msgid "Domain*" msgstr "" -#: ../gtk/setupwizard.c:130 +#: ../gtk/setupwizard.c:145 msgid "Proxy" msgstr "" -#: ../gtk/setupwizard.c:302 +#: ../gtk/setupwizard.c:317 msgid "(*) Required fields" msgstr "" -#: ../gtk/setupwizard.c:303 +#: ../gtk/setupwizard.c:318 #, fuzzy msgid "Username: (*)" msgstr "Nombre de usuario:" -#: ../gtk/setupwizard.c:305 +#: ../gtk/setupwizard.c:320 #, fuzzy msgid "Password: (*)" msgstr "Contraseña:" -#: ../gtk/setupwizard.c:307 +#: ../gtk/setupwizard.c:322 msgid "Email: (*)" msgstr "" -#: ../gtk/setupwizard.c:309 +#: ../gtk/setupwizard.c:324 msgid "Confirm your password: (*)" msgstr "" -#: ../gtk/setupwizard.c:373 +#: ../gtk/setupwizard.c:338 +msgid "Keep me informed with linphone updates" +msgstr "" + +#: ../gtk/setupwizard.c:394 msgid "" "Error, account not validated, username already used or server unreachable.\n" "Please go back and try again." msgstr "" -#: ../gtk/setupwizard.c:384 +#: ../gtk/setupwizard.c:405 msgid "Thank you. Your account is now configured and ready for use." msgstr "Gracias. Su cuenta está configurada y lista para su utilización." -#: ../gtk/setupwizard.c:392 +#: ../gtk/setupwizard.c:413 msgid "" "Please validate your account by clicking on the link we just sent you by " "email.\n" "Then come back here and press Next button." msgstr "" -#: ../gtk/setupwizard.c:564 +#: ../gtk/setupwizard.c:600 #, fuzzy msgid "SIP account configuration assistant" msgstr "Asistente de configuración de cuenta" -#: ../gtk/setupwizard.c:582 +#: ../gtk/setupwizard.c:618 msgid "Welcome to the account setup assistant" msgstr "Bienvenido al asistente de configuración de cuenta" -#: ../gtk/setupwizard.c:587 +#: ../gtk/setupwizard.c:623 msgid "Account setup assistant" msgstr "Asistente de configuración de cuenta" -#: ../gtk/setupwizard.c:593 +#: ../gtk/setupwizard.c:629 #, fuzzy msgid "Configure your account (step 1/1)" msgstr "Configurar una cuenta SIP" -#: ../gtk/setupwizard.c:598 +#: ../gtk/setupwizard.c:634 msgid "Enter your sip username (step 1/1)" msgstr "" -#: ../gtk/setupwizard.c:602 +#: ../gtk/setupwizard.c:638 msgid "Enter account information (step 1/2)" msgstr "" -#: ../gtk/setupwizard.c:611 +#: ../gtk/setupwizard.c:647 msgid "Validation (step 2/2)" msgstr "" -#: ../gtk/setupwizard.c:616 +#: ../gtk/setupwizard.c:652 msgid "Error" msgstr "" -#: ../gtk/setupwizard.c:620 ../gtk/audio_assistant.c:519 +#: ../gtk/setupwizard.c:656 ../gtk/audio_assistant.c:527 msgid "Terminating" msgstr "" @@ -661,136 +665,136 @@ msgstr "La llamada ha fallado." msgid "Direct or through server" msgstr "" -#: ../gtk/incall_view.c:266 ../gtk/incall_view.c:276 +#: ../gtk/incall_view.c:267 ../gtk/incall_view.c:279 #, c-format msgid "" "download: %f\n" "upload: %f (kbit/s)" msgstr "" -#: ../gtk/incall_view.c:271 ../gtk/incall_view.c:272 +#: ../gtk/incall_view.c:272 ../gtk/incall_view.c:274 #, c-format -msgid "%ix%i" +msgid "%ix%i @ %f fps" msgstr "" -#: ../gtk/incall_view.c:301 +#: ../gtk/incall_view.c:304 #, fuzzy, c-format msgid "%.3f seconds" msgstr "%i segundo" -#: ../gtk/incall_view.c:399 ../gtk/main.ui.h:12 +#: ../gtk/incall_view.c:407 ../gtk/main.ui.h:12 msgid "Hang up" msgstr "" -#: ../gtk/incall_view.c:492 +#: ../gtk/incall_view.c:501 #, fuzzy msgid "Calling..." msgstr " Llamando..." -#: ../gtk/incall_view.c:495 ../gtk/incall_view.c:698 +#: ../gtk/incall_view.c:504 ../gtk/incall_view.c:707 msgid "00::00::00" msgstr "00::00::00" -#: ../gtk/incall_view.c:506 +#: ../gtk/incall_view.c:515 #, fuzzy msgid "Incoming call" msgstr "Llamada entrante" -#: ../gtk/incall_view.c:543 +#: ../gtk/incall_view.c:552 msgid "good" msgstr "buena" -#: ../gtk/incall_view.c:545 +#: ../gtk/incall_view.c:554 msgid "average" msgstr "media" -#: ../gtk/incall_view.c:547 +#: ../gtk/incall_view.c:556 msgid "poor" msgstr "mala" -#: ../gtk/incall_view.c:549 +#: ../gtk/incall_view.c:558 msgid "very poor" msgstr "muy mala" -#: ../gtk/incall_view.c:551 +#: ../gtk/incall_view.c:560 msgid "too bad" msgstr "demasiado mala" -#: ../gtk/incall_view.c:552 ../gtk/incall_view.c:568 +#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:577 msgid "unavailable" msgstr "no disponible" -#: ../gtk/incall_view.c:660 +#: ../gtk/incall_view.c:669 msgid "Secured by SRTP" msgstr "Cifrada con SRTP" -#: ../gtk/incall_view.c:666 +#: ../gtk/incall_view.c:675 #, c-format msgid "Secured by ZRTP - [auth token: %s]" msgstr "Cifrada con ZRTP - [token de autenticación: %s]" -#: ../gtk/incall_view.c:672 +#: ../gtk/incall_view.c:681 msgid "Set unverified" msgstr "Set sin verificar" -#: ../gtk/incall_view.c:672 ../gtk/main.ui.h:4 +#: ../gtk/incall_view.c:681 ../gtk/main.ui.h:4 msgid "Set verified" msgstr "Set verificado" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In conference" msgstr "En conferencia" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 #, fuzzy msgid "In call" msgstr "En llamada " -#: ../gtk/incall_view.c:729 +#: ../gtk/incall_view.c:738 #, fuzzy msgid "Paused call" msgstr "Llamada en pausa" -#: ../gtk/incall_view.c:742 +#: ../gtk/incall_view.c:751 #, c-format msgid "%02i::%02i::%02i" msgstr "%02i::%02i::%02i" -#: ../gtk/incall_view.c:760 +#: ../gtk/incall_view.c:772 #, fuzzy msgid "Call ended." msgstr "Llamada finalizada." -#: ../gtk/incall_view.c:791 +#: ../gtk/incall_view.c:803 msgid "Transfer in progress" msgstr "" -#: ../gtk/incall_view.c:794 +#: ../gtk/incall_view.c:806 #, fuzzy msgid "Transfer done." msgstr "Transferir" -#: ../gtk/incall_view.c:797 +#: ../gtk/incall_view.c:809 #, fuzzy msgid "Transfer failed." msgstr "Transferir" -#: ../gtk/incall_view.c:841 +#: ../gtk/incall_view.c:853 msgid "Resume" msgstr "Reanudar" -#: ../gtk/incall_view.c:848 ../gtk/main.ui.h:9 +#: ../gtk/incall_view.c:860 ../gtk/main.ui.h:9 msgid "Pause" msgstr "Pausar" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, c-format msgid "" "Recording into\n" "%s %s" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, fuzzy msgid "(Paused)" msgstr "Pausar" @@ -826,7 +830,7 @@ msgstr "" msgid "Too loud" msgstr "" -#: ../gtk/audio_assistant.c:316 +#: ../gtk/audio_assistant.c:318 #, fuzzy msgid "" "Welcome !\n" @@ -835,60 +839,60 @@ msgstr "" "¡Bienvenido/a !\n" "Este asistente le ayudará a utilizar una cuenta SIP para sus llamadas." -#: ../gtk/audio_assistant.c:326 +#: ../gtk/audio_assistant.c:328 #, fuzzy msgid "Capture device" msgstr "Dispositivo de captura:" -#: ../gtk/audio_assistant.c:327 +#: ../gtk/audio_assistant.c:329 #, fuzzy msgid "Recorded volume" msgstr "Fuente de grabación:" -#: ../gtk/audio_assistant.c:331 +#: ../gtk/audio_assistant.c:333 msgid "No voice" msgstr "" -#: ../gtk/audio_assistant.c:367 +#: ../gtk/audio_assistant.c:369 #, fuzzy msgid "Playback device" msgstr "Dispositivo de reproducción:" -#: ../gtk/audio_assistant.c:368 +#: ../gtk/audio_assistant.c:370 msgid "Play three beeps" msgstr "" -#: ../gtk/audio_assistant.c:400 +#: ../gtk/audio_assistant.c:403 msgid "Press the record button and say some words" msgstr "" -#: ../gtk/audio_assistant.c:401 +#: ../gtk/audio_assistant.c:404 msgid "Listen to your record voice" msgstr "" -#: ../gtk/audio_assistant.c:430 +#: ../gtk/audio_assistant.c:433 msgid "Let's start Linphone now" msgstr "" -#: ../gtk/audio_assistant.c:488 +#: ../gtk/audio_assistant.c:496 #, fuzzy msgid "Audio Assistant" msgstr "Asistente de configuración de cuenta" -#: ../gtk/audio_assistant.c:498 ../gtk/main.ui.h:31 +#: ../gtk/audio_assistant.c:506 ../gtk/main.ui.h:31 #, fuzzy msgid "Audio assistant" msgstr "Asistente de configuración de cuenta" -#: ../gtk/audio_assistant.c:503 +#: ../gtk/audio_assistant.c:511 msgid "Mic Gain calibration" msgstr "" -#: ../gtk/audio_assistant.c:509 +#: ../gtk/audio_assistant.c:517 msgid "Speaker volume calibration" msgstr "" -#: ../gtk/audio_assistant.c:514 +#: ../gtk/audio_assistant.c:522 msgid "Record and Play" msgstr "" @@ -1901,101 +1905,70 @@ msgstr "Conectando..." msgid "Please wait while fetching configuration from server..." msgstr "" -#: ../coreapi/linphonecore.c:242 -msgid "aborted" -msgstr "abortada" - -#: ../coreapi/linphonecore.c:245 -msgid "completed" -msgstr "completada" - -#: ../coreapi/linphonecore.c:248 -msgid "missed" -msgstr "perdida" - -#: ../coreapi/linphonecore.c:253 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" -"%s en %s\n" -"De: %s\n" -"Para: %s\n" -"Estado: %s\n" -"Duración: %i min %i seg\n" - -#: ../coreapi/linphonecore.c:254 -msgid "Outgoing call" -msgstr "Llamada saliente" - -#: ../coreapi/linphonecore.c:1287 +#: ../coreapi/linphonecore.c:1034 #, fuzzy msgid "Ready" msgstr "Preparado" -#: ../coreapi/linphonecore.c:2248 +#: ../coreapi/linphonecore.c:1967 #, fuzzy msgid "Configuring" msgstr "Confirmación" -#: ../coreapi/linphonecore.c:2410 +#: ../coreapi/linphonecore.c:2133 msgid "Looking for telephone number destination..." msgstr "Buscando el número de teléfono del destinatario…" -#: ../coreapi/linphonecore.c:2413 +#: ../coreapi/linphonecore.c:2136 msgid "Could not resolve this number." msgstr "No se ha podido resolver este número." #. must be known at that time -#: ../coreapi/linphonecore.c:2695 +#: ../coreapi/linphonecore.c:2418 #, fuzzy msgid "Contacting" msgstr "Contactando" -#: ../coreapi/linphonecore.c:2702 +#: ../coreapi/linphonecore.c:2425 #, fuzzy msgid "Could not call" msgstr "No se pudo llamar" -#: ../coreapi/linphonecore.c:2852 +#: ../coreapi/linphonecore.c:2576 msgid "Sorry, we have reached the maximum number of simultaneous calls" msgstr "Disculpe, se ha alcanzado el máximo número de llamadas simultáneas" -#: ../coreapi/linphonecore.c:3022 +#: ../coreapi/linphonecore.c:2745 #, fuzzy msgid "is contacting you" msgstr "le está llamando" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid " and asked autoanswer." msgstr "y ha solicitado auto respuesta." -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid "." msgstr "." -#: ../coreapi/linphonecore.c:3139 +#: ../coreapi/linphonecore.c:2865 msgid "Modifying call parameters..." msgstr "Modificando parámetros de llamada…" -#: ../coreapi/linphonecore.c:3469 +#: ../coreapi/linphonecore.c:3194 msgid "Connected." msgstr "Conectado." -#: ../coreapi/linphonecore.c:3495 +#: ../coreapi/linphonecore.c:3220 #, fuzzy msgid "Call aborted" msgstr "Llamada abortada" -#: ../coreapi/linphonecore.c:3685 +#: ../coreapi/linphonecore.c:3412 msgid "Could not pause the call" msgstr "No se pudo pausar la llamada" -#: ../coreapi/linphonecore.c:3690 +#: ../coreapi/linphonecore.c:3417 msgid "Pausing the current call..." msgstr "Pausando la llamada actual..." @@ -2064,7 +2037,7 @@ msgstr "Duración" msgid "Unknown-bug" msgstr "Bug-desconocido" -#: ../coreapi/proxy.c:279 +#: ../coreapi/proxy.c:314 msgid "" "The sip proxy address you entered is invalid, it must start with \"sip:\" " "followed by a hostname." @@ -2072,7 +2045,7 @@ msgstr "" "La dirección del Proxy SIP que ha introducido no es válida, debe empezar con " "\"sip:\" seguido del hostname." -#: ../coreapi/proxy.c:285 +#: ../coreapi/proxy.c:320 msgid "" "The sip identity you entered is invalid.\n" "It should look like sip:username@proxydomain, such as sip:alice@example.net" @@ -2081,137 +2054,162 @@ msgstr "" "Debe ser del tipo sip:username@proxydomain, como por ejemplo sip:" "alice@example.net" -#: ../coreapi/proxy.c:1299 +#: ../coreapi/proxy.c:1369 #, fuzzy, c-format msgid "Could not login as %s" msgstr "No se pudo iniciar sesión como %s" -#: ../coreapi/callbacks.c:354 +#: ../coreapi/callbacks.c:355 #, fuzzy msgid "Remote ringing." msgstr "El destinatario está sonando..." -#: ../coreapi/callbacks.c:370 +#: ../coreapi/callbacks.c:373 #, fuzzy msgid "Remote ringing..." msgstr "El destinatario está sonando..." -#: ../coreapi/callbacks.c:381 +#: ../coreapi/callbacks.c:384 msgid "Early media." msgstr "Medios iniciales." -#: ../coreapi/callbacks.c:432 +#: ../coreapi/callbacks.c:435 #, c-format msgid "Call with %s is paused." msgstr "La llamada con %s está puesta en pausa." -#: ../coreapi/callbacks.c:445 +#: ../coreapi/callbacks.c:448 #, c-format msgid "Call answered by %s - on hold." msgstr "Llamada respondida por %s - en espera." -#: ../coreapi/callbacks.c:456 +#: ../coreapi/callbacks.c:459 #, fuzzy msgid "Call resumed." msgstr "Llamada reanudada." -#: ../coreapi/callbacks.c:461 +#: ../coreapi/callbacks.c:464 #, fuzzy, c-format msgid "Call answered by %s." msgstr "Llamada respondida por %s." -#: ../coreapi/callbacks.c:480 +#: ../coreapi/callbacks.c:483 msgid "Incompatible, check codecs or security settings..." msgstr "" -#: ../coreapi/callbacks.c:531 +#: ../coreapi/callbacks.c:512 #, fuzzy msgid "We have been resumed." msgstr "Nos han reanudado..." -#: ../coreapi/callbacks.c:541 +#: ../coreapi/callbacks.c:521 msgid "We are paused by other party." msgstr "" -#: ../coreapi/callbacks.c:558 +#: ../coreapi/callbacks.c:556 #, fuzzy msgid "Call is updated by remote." msgstr "La llamada ha sido actualizada por el destinatario..." -#: ../coreapi/callbacks.c:637 +#: ../coreapi/callbacks.c:658 #, fuzzy msgid "Call terminated." msgstr "Llamada finalizada." -#: ../coreapi/callbacks.c:666 +#: ../coreapi/callbacks.c:687 msgid "User is busy." msgstr "El usuario está ocupado." -#: ../coreapi/callbacks.c:667 +#: ../coreapi/callbacks.c:688 msgid "User is temporarily unavailable." msgstr "El usuario no está disponible temporalmente." #. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:669 +#: ../coreapi/callbacks.c:690 msgid "User does not want to be disturbed." msgstr "El usuario no quiere que le molesten." -#: ../coreapi/callbacks.c:670 +#: ../coreapi/callbacks.c:691 msgid "Call declined." msgstr "Llamada rechazada." -#: ../coreapi/callbacks.c:685 +#: ../coreapi/callbacks.c:706 msgid "Request timeout." msgstr "" -#: ../coreapi/callbacks.c:716 +#: ../coreapi/callbacks.c:737 msgid "Redirected" msgstr "Redigirida" -#: ../coreapi/callbacks.c:766 +#: ../coreapi/callbacks.c:787 msgid "Incompatible media parameters." msgstr "" -#: ../coreapi/callbacks.c:777 +#: ../coreapi/callbacks.c:798 #, fuzzy msgid "Call failed." msgstr "La llamada ha fallado." -#: ../coreapi/callbacks.c:852 +#: ../coreapi/callbacks.c:878 #, fuzzy, c-format msgid "Registration on %s successful." msgstr "Se ha registrado con éxito en %s." -#: ../coreapi/callbacks.c:853 +#: ../coreapi/callbacks.c:879 #, fuzzy, c-format msgid "Unregistration on %s done." msgstr "Cancelación de registro en %s completada." -#: ../coreapi/callbacks.c:875 +#: ../coreapi/callbacks.c:897 msgid "no response timeout" msgstr "timeout sin respuesta" -#: ../coreapi/callbacks.c:878 +#: ../coreapi/callbacks.c:900 #, fuzzy, c-format msgid "Registration on %s failed: %s" msgstr "El registro en %s ha fallado." -#: ../coreapi/callbacks.c:885 +#: ../coreapi/callbacks.c:907 msgid "Service unavailable, retrying" msgstr "" -#: ../coreapi/linphonecall.c:175 +#: ../coreapi/linphonecall.c:177 #, fuzzy, c-format msgid "Authentication token is %s" msgstr "El tóken de autenticación es%s" -#: ../coreapi/linphonecall.c:2994 +#: ../coreapi/linphonecall.c:2932 #, c-format msgid "You have missed %i call." msgid_plural "You have missed %i calls." msgstr[0] "Tiene %i llamada perdida." msgstr[1] "Tiene %i llamadas perdidas." +#~ msgid "aborted" +#~ msgstr "abortada" + +#~ msgid "completed" +#~ msgstr "completada" + +#~ msgid "missed" +#~ msgstr "perdida" + +#~ msgid "" +#~ "%s at %s\n" +#~ "From: %s\n" +#~ "To: %s\n" +#~ "Status: %s\n" +#~ "Duration: %i mn %i sec\n" +#~ msgstr "" +#~ "%s en %s\n" +#~ "De: %s\n" +#~ "Para: %s\n" +#~ "Estado: %s\n" +#~ "Duración: %i min %i seg\n" + +#~ msgid "Outgoing call" +#~ msgstr "Llamada saliente" + #~ msgid "No response." #~ msgstr "No hay respuesta." diff --git a/po/fr.po b/po/fr.po index 892b7f1c9..a7aac8717 100644 --- a/po/fr.po +++ b/po/fr.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: Linphone 0.9.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-01 21:24+0200\n" +"POT-Creation-Date: 2014-09-15 09:24+0200\n" "PO-Revision-Date: 2013-04-09 13:57+0100\n" "Last-Translator: Simon Morlat \n" "Language-Team: french \n" @@ -15,12 +15,12 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:973 +#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:974 #, c-format msgid "Call %s" msgstr "Appeler %s" -#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:974 +#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:975 #, c-format msgid "Send text to %s" msgstr "Chatter avec %s" @@ -30,42 +30,42 @@ msgstr "Chatter avec %s" msgid "Recent calls (%i)" msgstr "Appels récents (%i)" -#: ../gtk/calllogs.c:312 +#: ../gtk/calllogs.c:314 msgid "n/a" msgstr "inconnu" -#: ../gtk/calllogs.c:315 +#: ../gtk/calllogs.c:317 msgid "Aborted" msgstr "Abandonné" -#: ../gtk/calllogs.c:318 +#: ../gtk/calllogs.c:320 msgid "Missed" msgstr "Manqué" -#: ../gtk/calllogs.c:321 +#: ../gtk/calllogs.c:323 msgid "Declined" msgstr "Refusé" -#: ../gtk/calllogs.c:327 +#: ../gtk/calllogs.c:329 #, c-format msgid "%i minute" msgid_plural "%i minutes" msgstr[0] "" msgstr[1] "" -#: ../gtk/calllogs.c:330 +#: ../gtk/calllogs.c:332 #, c-format msgid "%i second" msgid_plural "%i seconds" msgstr[0] "%i seconde" msgstr[1] "%i secondes" -#: ../gtk/calllogs.c:333 ../gtk/calllogs.c:339 +#: ../gtk/calllogs.c:335 ../gtk/calllogs.c:341 #, c-format msgid "%s\t%s" msgstr "" -#: ../gtk/calllogs.c:335 +#: ../gtk/calllogs.c:337 #, c-format msgid "" "%s\tQuality: %s\n" @@ -74,7 +74,7 @@ msgstr "" "%s\tQualité: %s\n" "%s\t%s\t" -#: ../gtk/calllogs.c:341 +#: ../gtk/calllogs.c:343 #, c-format msgid "" "%s\t\n" @@ -94,7 +94,7 @@ msgstr "Moi" msgid "Couldn't find pixmap file: %s" msgstr "Icone non trouvée: %s" -#: ../gtk/chat.c:363 ../gtk/friendlist.c:923 +#: ../gtk/chat.c:364 ../gtk/friendlist.c:924 msgid "Invalid sip contact !" msgstr "Contact sip invalide !" @@ -143,7 +143,7 @@ msgstr "Démarre l'assistant audio" msgid "Call with %s" msgstr "Appel avec %s" -#: ../gtk/main.c:1171 +#: ../gtk/main.c:1183 #, c-format msgid "" "%s would like to add you to his contact list.\n" @@ -157,7 +157,7 @@ msgstr "" "Si vous répondez non, cette personne sera mise temporairement sur liste " "noire." -#: ../gtk/main.c:1248 +#: ../gtk/main.c:1260 #, c-format msgid "" "Please enter your password for username %s\n" @@ -166,59 +166,59 @@ msgstr "" "Entrez le mot de passe pour %s\n" " sur le domaine %s:" -#: ../gtk/main.c:1364 +#: ../gtk/main.c:1376 msgid "Call error" msgstr "Erreur lors de l'appel" -#: ../gtk/main.c:1367 ../coreapi/linphonecore.c:3515 +#: ../gtk/main.c:1379 ../coreapi/linphonecore.c:3240 msgid "Call ended" msgstr "Appel terminé." -#: ../gtk/main.c:1370 ../coreapi/linphonecore.c:254 +#: ../gtk/main.c:1382 msgid "Incoming call" msgstr "Appel entrant" -#: ../gtk/main.c:1372 ../gtk/incall_view.c:513 ../gtk/main.ui.h:5 +#: ../gtk/main.c:1384 ../gtk/incall_view.c:522 ../gtk/main.ui.h:5 msgid "Answer" msgstr "Répondre" -#: ../gtk/main.c:1374 ../gtk/main.ui.h:6 +#: ../gtk/main.c:1386 ../gtk/main.ui.h:6 msgid "Decline" msgstr "Refuser" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 msgid "Call paused" msgstr "Appel en pause" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, c-format msgid "by %s" msgstr "b>par %s" -#: ../gtk/main.c:1447 +#: ../gtk/main.c:1459 #, c-format msgid "%s proposed to start video. Do you accept ?" msgstr "%s propose de démarrer la vidéo. Acceptez-vous ?" -#: ../gtk/main.c:1609 +#: ../gtk/main.c:1621 msgid "Website link" msgstr "Lien site web" -#: ../gtk/main.c:1658 +#: ../gtk/main.c:1670 msgid "Linphone - a video internet phone" msgstr "Linphone - un téléphone video pour l'internet" -#: ../gtk/main.c:1750 +#: ../gtk/main.c:1762 #, c-format msgid "%s (Default)" msgstr "%s (par défaut)" -#: ../gtk/main.c:2086 ../coreapi/callbacks.c:927 +#: ../gtk/main.c:2099 ../coreapi/callbacks.c:949 #, c-format msgid "We are transferred to %s" msgstr "Transfert vers %s" -#: ../gtk/main.c:2096 +#: ../gtk/main.c:2109 msgid "" "No sound cards have been detected on this computer.\n" "You won't be able to send or receive audio calls." @@ -226,7 +226,7 @@ msgstr "" "Aucune carte son n'a été détectée sur cet ordinateur.\n" "Vous ne pourrez pas effectuer d'appels audio." -#: ../gtk/main.c:2237 +#: ../gtk/main.c:2250 msgid "A free SIP video-phone" msgstr "Un visiophone libre" @@ -238,7 +238,7 @@ msgstr "Ajouter au carnet d'adresse" msgid "Presence status" msgstr "Info de présence" -#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:550 ../gtk/contact.ui.h:1 +#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:552 ../gtk/contact.ui.h:1 msgid "Name" msgstr "Nom" @@ -255,142 +255,142 @@ msgstr "" msgid "Search in %s directory" msgstr "Rechercher dans l'annuaire de %s" -#: ../gtk/friendlist.c:975 +#: ../gtk/friendlist.c:976 #, c-format msgid "Edit contact '%s'" msgstr "Editer le contact '%s'" -#: ../gtk/friendlist.c:976 +#: ../gtk/friendlist.c:977 #, c-format msgid "Delete contact '%s'" msgstr "Supprimer le contact '%s'" -#: ../gtk/friendlist.c:977 +#: ../gtk/friendlist.c:978 #, c-format msgid "Delete chat history of '%s'" msgstr "Supprimer l'historique de chat de '%s'" -#: ../gtk/friendlist.c:1028 +#: ../gtk/friendlist.c:1029 #, c-format msgid "Add new contact from %s directory" msgstr "Ajouter un contact depuis l'annuaire %s" -#: ../gtk/propertybox.c:556 +#: ../gtk/propertybox.c:558 msgid "Rate (Hz)" msgstr "Fréquence (Hz)" -#: ../gtk/propertybox.c:562 +#: ../gtk/propertybox.c:564 msgid "Status" msgstr "Etat" -#: ../gtk/propertybox.c:568 +#: ../gtk/propertybox.c:570 msgid "IP Bitrate (kbit/s)" msgstr "Débit IP (kbit/s)" -#: ../gtk/propertybox.c:575 +#: ../gtk/propertybox.c:577 msgid "Parameters" msgstr "Paramètres" -#: ../gtk/propertybox.c:618 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:763 msgid "Enabled" msgstr "Activé" -#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:622 ../gtk/propertybox.c:763 msgid "Disabled" msgstr "Désactivé" -#: ../gtk/propertybox.c:807 +#: ../gtk/propertybox.c:809 msgid "Account" msgstr "Compte" -#: ../gtk/propertybox.c:1061 +#: ../gtk/propertybox.c:1063 msgid "English" msgstr "Anglais" -#: ../gtk/propertybox.c:1062 +#: ../gtk/propertybox.c:1064 msgid "French" msgstr "Français" -#: ../gtk/propertybox.c:1063 +#: ../gtk/propertybox.c:1065 msgid "Swedish" msgstr "Suédois" -#: ../gtk/propertybox.c:1064 +#: ../gtk/propertybox.c:1066 msgid "Italian" msgstr "Italien" -#: ../gtk/propertybox.c:1065 +#: ../gtk/propertybox.c:1067 msgid "Spanish" msgstr "Espagnol" -#: ../gtk/propertybox.c:1066 +#: ../gtk/propertybox.c:1068 msgid "Brazilian Portugese" msgstr "Portugais brésilien" -#: ../gtk/propertybox.c:1067 +#: ../gtk/propertybox.c:1069 msgid "Polish" msgstr "Polonais" -#: ../gtk/propertybox.c:1068 +#: ../gtk/propertybox.c:1070 msgid "German" msgstr "Allemand" -#: ../gtk/propertybox.c:1069 +#: ../gtk/propertybox.c:1071 msgid "Russian" msgstr "Russe" -#: ../gtk/propertybox.c:1070 +#: ../gtk/propertybox.c:1072 msgid "Japanese" msgstr "日本語" -#: ../gtk/propertybox.c:1071 +#: ../gtk/propertybox.c:1073 msgid "Dutch" msgstr "Néérlandais" -#: ../gtk/propertybox.c:1072 +#: ../gtk/propertybox.c:1074 msgid "Hungarian" msgstr "Hongrois" -#: ../gtk/propertybox.c:1073 +#: ../gtk/propertybox.c:1075 msgid "Czech" msgstr "Tchèque" -#: ../gtk/propertybox.c:1074 +#: ../gtk/propertybox.c:1076 msgid "Chinese" msgstr "简体中文" -#: ../gtk/propertybox.c:1075 +#: ../gtk/propertybox.c:1077 msgid "Traditional Chinese" msgstr "Chinois traditionnel" -#: ../gtk/propertybox.c:1076 +#: ../gtk/propertybox.c:1078 msgid "Norwegian" msgstr "Norvégien" -#: ../gtk/propertybox.c:1077 +#: ../gtk/propertybox.c:1079 msgid "Hebrew" msgstr "Hébreu" -#: ../gtk/propertybox.c:1078 +#: ../gtk/propertybox.c:1080 msgid "Serbian" msgstr "Serbe" -#: ../gtk/propertybox.c:1145 +#: ../gtk/propertybox.c:1147 msgid "" "You need to restart linphone for the new language selection to take effect." msgstr "" "La nouvelle selection de langue prendra effet au prochain démarrage de " "linphone." -#: ../gtk/propertybox.c:1223 +#: ../gtk/propertybox.c:1225 msgid "None" msgstr "Aucun" -#: ../gtk/propertybox.c:1227 +#: ../gtk/propertybox.c:1229 msgid "SRTP" msgstr "" -#: ../gtk/propertybox.c:1233 +#: ../gtk/propertybox.c:1235 msgid "ZRTP" msgstr "" @@ -463,55 +463,59 @@ msgstr "Je veux spécifier une URI de configuration" msgid "Enter your linphone.org username" msgstr "Entrez votre identifiant linphone.org" -#: ../gtk/setupwizard.c:96 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 +#: ../gtk/setupwizard.c:102 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 msgid "Username:" msgstr "Nom d'utilisateur:" -#: ../gtk/setupwizard.c:98 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 +#: ../gtk/setupwizard.c:104 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 msgid "Password:" msgstr "Mot de passe:" -#: ../gtk/setupwizard.c:118 +#: ../gtk/setupwizard.c:124 msgid "Enter your account informations" msgstr "Entrez les informations concernant votre compte" -#: ../gtk/setupwizard.c:125 +#: ../gtk/setupwizard.c:140 msgid "Username*" msgstr "Nom d'utilisateur*" -#: ../gtk/setupwizard.c:126 +#: ../gtk/setupwizard.c:141 msgid "Password*" msgstr "Mot de passe*" -#: ../gtk/setupwizard.c:129 +#: ../gtk/setupwizard.c:144 msgid "Domain*" msgstr "Domaine*" -#: ../gtk/setupwizard.c:130 +#: ../gtk/setupwizard.c:145 msgid "Proxy" msgstr "" -#: ../gtk/setupwizard.c:302 +#: ../gtk/setupwizard.c:317 msgid "(*) Required fields" msgstr "(*) Champs requis" -#: ../gtk/setupwizard.c:303 +#: ../gtk/setupwizard.c:318 msgid "Username: (*)" msgstr "Nom d'utilisateur: (*)" -#: ../gtk/setupwizard.c:305 +#: ../gtk/setupwizard.c:320 msgid "Password: (*)" msgstr "Mot de passe: (*)" -#: ../gtk/setupwizard.c:307 +#: ../gtk/setupwizard.c:322 msgid "Email: (*)" msgstr "" -#: ../gtk/setupwizard.c:309 +#: ../gtk/setupwizard.c:324 msgid "Confirm your password: (*)" msgstr "Confirmez votre mot de passe: (*)" -#: ../gtk/setupwizard.c:373 +#: ../gtk/setupwizard.c:338 +msgid "Keep me informed with linphone updates" +msgstr "" + +#: ../gtk/setupwizard.c:394 msgid "" "Error, account not validated, username already used or server unreachable.\n" "Please go back and try again." @@ -520,11 +524,11 @@ msgstr "" "serveur n'est pas accessible.\n" "Merci d'essayer à nouveau." -#: ../gtk/setupwizard.c:384 +#: ../gtk/setupwizard.c:405 msgid "Thank you. Your account is now configured and ready for use." msgstr "Merci. Votre compte est maintenant configuré et prêt à être utilisé." -#: ../gtk/setupwizard.c:392 +#: ../gtk/setupwizard.c:413 msgid "" "Please validate your account by clicking on the link we just sent you by " "email.\n" @@ -534,39 +538,39 @@ msgstr "" "par email.\n" "Puis appuyez sur suivant." -#: ../gtk/setupwizard.c:564 +#: ../gtk/setupwizard.c:600 msgid "SIP account configuration assistant" msgstr "Assistant de configuration de compte." -#: ../gtk/setupwizard.c:582 +#: ../gtk/setupwizard.c:618 msgid "Welcome to the account setup assistant" msgstr "Bienvenue dans l'assistant de configuration de compte." -#: ../gtk/setupwizard.c:587 +#: ../gtk/setupwizard.c:623 msgid "Account setup assistant" msgstr "Assistant de configuration de compte." -#: ../gtk/setupwizard.c:593 +#: ../gtk/setupwizard.c:629 msgid "Configure your account (step 1/1)" msgstr "Configurez votre compte (étape 1/1)" -#: ../gtk/setupwizard.c:598 +#: ../gtk/setupwizard.c:634 msgid "Enter your sip username (step 1/1)" msgstr "Entrez votre identifiant sip (étape 1/1)" -#: ../gtk/setupwizard.c:602 +#: ../gtk/setupwizard.c:638 msgid "Enter account information (step 1/2)" msgstr "Entrez les informations concernant votre compte (étape 1/2)" -#: ../gtk/setupwizard.c:611 +#: ../gtk/setupwizard.c:647 msgid "Validation (step 2/2)" msgstr "Validation (étape 2/2)" -#: ../gtk/setupwizard.c:616 +#: ../gtk/setupwizard.c:652 msgid "Error" msgstr "Erreur" -#: ../gtk/setupwizard.c:620 ../gtk/audio_assistant.c:519 +#: ../gtk/setupwizard.c:656 ../gtk/audio_assistant.c:527 msgid "Terminating" msgstr "En cours d’arrêt." @@ -632,129 +636,129 @@ msgstr "uPnP a échoué." msgid "Direct or through server" msgstr "Directe ou via un serveur" -#: ../gtk/incall_view.c:266 ../gtk/incall_view.c:276 +#: ../gtk/incall_view.c:267 ../gtk/incall_view.c:279 #, c-format msgid "" "download: %f\n" "upload: %f (kbit/s)" msgstr "" -#: ../gtk/incall_view.c:271 ../gtk/incall_view.c:272 +#: ../gtk/incall_view.c:272 ../gtk/incall_view.c:274 #, c-format -msgid "%ix%i" +msgid "%ix%i @ %f fps" msgstr "" -#: ../gtk/incall_view.c:301 +#: ../gtk/incall_view.c:304 #, c-format msgid "%.3f seconds" msgstr "" -#: ../gtk/incall_view.c:399 ../gtk/main.ui.h:12 +#: ../gtk/incall_view.c:407 ../gtk/main.ui.h:12 msgid "Hang up" msgstr "Raccrocher" -#: ../gtk/incall_view.c:492 +#: ../gtk/incall_view.c:501 msgid "Calling..." msgstr "Tentative d'appel..." -#: ../gtk/incall_view.c:495 ../gtk/incall_view.c:698 +#: ../gtk/incall_view.c:504 ../gtk/incall_view.c:707 msgid "00::00::00" msgstr "" -#: ../gtk/incall_view.c:506 +#: ../gtk/incall_view.c:515 msgid "Incoming call" msgstr "Appel entrant" -#: ../gtk/incall_view.c:543 +#: ../gtk/incall_view.c:552 msgid "good" msgstr "bon" -#: ../gtk/incall_view.c:545 +#: ../gtk/incall_view.c:554 msgid "average" msgstr "moyen" -#: ../gtk/incall_view.c:547 +#: ../gtk/incall_view.c:556 msgid "poor" msgstr "faible" -#: ../gtk/incall_view.c:549 +#: ../gtk/incall_view.c:558 msgid "very poor" msgstr "très faible" -#: ../gtk/incall_view.c:551 +#: ../gtk/incall_view.c:560 msgid "too bad" msgstr "nulle" -#: ../gtk/incall_view.c:552 ../gtk/incall_view.c:568 +#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:577 msgid "unavailable" msgstr "indisponible" -#: ../gtk/incall_view.c:660 +#: ../gtk/incall_view.c:669 msgid "Secured by SRTP" msgstr "Sécurisé par SRTP" -#: ../gtk/incall_view.c:666 +#: ../gtk/incall_view.c:675 #, c-format msgid "Secured by ZRTP - [auth token: %s]" msgstr "Sécurisé par ZRTP- [jeton: %s]" -#: ../gtk/incall_view.c:672 +#: ../gtk/incall_view.c:681 msgid "Set unverified" msgstr "Marquer comme non vérifié" -#: ../gtk/incall_view.c:672 ../gtk/main.ui.h:4 +#: ../gtk/incall_view.c:681 ../gtk/main.ui.h:4 msgid "Set verified" msgstr "Marquer comme vérifié" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In conference" msgstr "En conférence" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In call" msgstr "Appel en cours" -#: ../gtk/incall_view.c:729 +#: ../gtk/incall_view.c:738 msgid "Paused call" msgstr "Appel en attente" -#: ../gtk/incall_view.c:742 +#: ../gtk/incall_view.c:751 #, c-format msgid "%02i::%02i::%02i" msgstr "" -#: ../gtk/incall_view.c:760 +#: ../gtk/incall_view.c:772 msgid "Call ended." msgstr "Appel terminé." -#: ../gtk/incall_view.c:791 +#: ../gtk/incall_view.c:803 msgid "Transfer in progress" msgstr "Transfert en cours" -#: ../gtk/incall_view.c:794 +#: ../gtk/incall_view.c:806 msgid "Transfer done." msgstr "Transfert terminé" -#: ../gtk/incall_view.c:797 +#: ../gtk/incall_view.c:809 msgid "Transfer failed." msgstr "Transfert échoué" -#: ../gtk/incall_view.c:841 +#: ../gtk/incall_view.c:853 msgid "Resume" msgstr "Reprendre" -#: ../gtk/incall_view.c:848 ../gtk/main.ui.h:9 +#: ../gtk/incall_view.c:860 ../gtk/main.ui.h:9 msgid "Pause" msgstr "Pause" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, c-format msgid "" "Recording into\n" "%s %s" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 msgid "(Paused)" msgstr "(en attente)" @@ -789,63 +793,64 @@ msgstr "" msgid "Too loud" msgstr "" -#: ../gtk/audio_assistant.c:316 +#: ../gtk/audio_assistant.c:318 msgid "" "Welcome !\n" "This assistant will help you to configure audio settings for Linphone" msgstr "" "Bienvenue!\n" -"Cet assistant va vous aider à régler les paramètres audio de votre ordinateur pour une utilisation optimale avec Linphone." +"Cet assistant va vous aider à régler les paramètres audio de votre " +"ordinateur pour une utilisation optimale avec Linphone." -#: ../gtk/audio_assistant.c:326 +#: ../gtk/audio_assistant.c:328 msgid "Capture device" msgstr "Périphérique de capture" -#: ../gtk/audio_assistant.c:327 +#: ../gtk/audio_assistant.c:329 msgid "Recorded volume" msgstr "Volume enregistré" -#: ../gtk/audio_assistant.c:331 +#: ../gtk/audio_assistant.c:333 msgid "No voice" msgstr "Silencieux" -#: ../gtk/audio_assistant.c:367 +#: ../gtk/audio_assistant.c:369 msgid "Playback device" msgstr "Périphérique d'écoute" -#: ../gtk/audio_assistant.c:368 +#: ../gtk/audio_assistant.c:370 msgid "Play three beeps" msgstr "Joue trois bips" -#: ../gtk/audio_assistant.c:400 +#: ../gtk/audio_assistant.c:403 msgid "Press the record button and say some words" msgstr "Appuyer sur le bouton enregistrer et dites quelques mots" -#: ../gtk/audio_assistant.c:401 +#: ../gtk/audio_assistant.c:404 msgid "Listen to your record voice" msgstr "Ecoutez votre voix enregistrée" -#: ../gtk/audio_assistant.c:430 +#: ../gtk/audio_assistant.c:433 msgid "Let's start Linphone now" msgstr "Démarrons Linphone maintenant" -#: ../gtk/audio_assistant.c:488 +#: ../gtk/audio_assistant.c:496 msgid "Audio Assistant" msgstr "Assistant audio" -#: ../gtk/audio_assistant.c:498 ../gtk/main.ui.h:31 +#: ../gtk/audio_assistant.c:506 ../gtk/main.ui.h:31 msgid "Audio assistant" msgstr "Assistant audio" -#: ../gtk/audio_assistant.c:503 +#: ../gtk/audio_assistant.c:511 msgid "Mic Gain calibration" msgstr "Calibration du gain du microphone" -#: ../gtk/audio_assistant.c:509 +#: ../gtk/audio_assistant.c:517 msgid "Speaker volume calibration" msgstr "Calibration du volume du haut parleur" -#: ../gtk/audio_assistant.c:514 +#: ../gtk/audio_assistant.c:522 msgid "Record and Play" msgstr "Enregistrer et joue" @@ -1579,11 +1584,11 @@ msgstr "" #: ../gtk/tunnel_config.ui.h:6 msgid "Configure tunnel" -msgstr "Configuration du tunnel" +msgstr "Configuration du tunnel" #: ../gtk/tunnel_config.ui.h:9 msgid "Configure http proxy (optional)" -msgstr "Configuration d'un proxy http (optionel)" +msgstr "Configuration d'un proxy http (optionel)" #: ../gtk/keypad.ui.h:1 msgid "D" @@ -1748,8 +1753,9 @@ msgid "" msgstr "" "Cette boite de dialogue vous permet de spécifier une addresse http ou https " "où la configuration doit être téléchargée au démarrage.\n" -"Veuillez entrer l'URI http(s) ci dessous. Après avoir validé, Linphone va redémarrer " -"automatiquement pour charger et prendre en compte la nouvelle configuration." +"Veuillez entrer l'URI http(s) ci dessous. Après avoir validé, Linphone va " +"redémarrer automatiquement pour charger et prendre en compte la nouvelle " +"configuration." #: ../gtk/config-uri.ui.h:4 msgid "https://" @@ -1765,95 +1771,64 @@ msgstr "" "Veuillez patenter un instant pendant le chargement de la configuration " "distante..." -#: ../coreapi/linphonecore.c:242 -msgid "aborted" -msgstr "abandonné" - -#: ../coreapi/linphonecore.c:245 -msgid "completed" -msgstr "terminé" - -#: ../coreapi/linphonecore.c:248 -msgid "missed" -msgstr "manqué" - -#: ../coreapi/linphonecore.c:253 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" -"%s le %s\n" -"De: %s\n" -"A destination de: %s\n" -"Etat: %s\n" -"Durée: %i mn %i sec\n" - -#: ../coreapi/linphonecore.c:254 -msgid "Outgoing call" -msgstr "Appel sortant" - -#: ../coreapi/linphonecore.c:1287 +#: ../coreapi/linphonecore.c:1034 msgid "Ready" msgstr "Prêt." -#: ../coreapi/linphonecore.c:2248 +#: ../coreapi/linphonecore.c:1967 msgid "Configuring" msgstr "Configuration en cours" -#: ../coreapi/linphonecore.c:2410 +#: ../coreapi/linphonecore.c:2133 msgid "Looking for telephone number destination..." msgstr "Recherche de la destination du numéro de téléphone..." -#: ../coreapi/linphonecore.c:2413 +#: ../coreapi/linphonecore.c:2136 msgid "Could not resolve this number." msgstr "La destination n'a pu être trouvée." #. must be known at that time -#: ../coreapi/linphonecore.c:2695 +#: ../coreapi/linphonecore.c:2418 msgid "Contacting" msgstr "Appel de" -#: ../coreapi/linphonecore.c:2702 +#: ../coreapi/linphonecore.c:2425 msgid "Could not call" msgstr "Echec de l'appel" -#: ../coreapi/linphonecore.c:2852 +#: ../coreapi/linphonecore.c:2576 msgid "Sorry, we have reached the maximum number of simultaneous calls" msgstr "Désolé, le nombre maximum d'appels simultanés est atteint." -#: ../coreapi/linphonecore.c:3022 +#: ../coreapi/linphonecore.c:2745 msgid "is contacting you" msgstr "vous appelle" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid " and asked autoanswer." msgstr "et sollicite un décrochage automatique." -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid "." msgstr "" -#: ../coreapi/linphonecore.c:3139 +#: ../coreapi/linphonecore.c:2865 msgid "Modifying call parameters..." msgstr "Modifications des paramètres d'appels..." -#: ../coreapi/linphonecore.c:3469 +#: ../coreapi/linphonecore.c:3194 msgid "Connected." msgstr "En ligne." -#: ../coreapi/linphonecore.c:3495 +#: ../coreapi/linphonecore.c:3220 msgid "Call aborted" msgstr "Appel abandonné" -#: ../coreapi/linphonecore.c:3685 +#: ../coreapi/linphonecore.c:3412 msgid "Could not pause the call" msgstr "La mise en attente a échoué" -#: ../coreapi/linphonecore.c:3690 +#: ../coreapi/linphonecore.c:3417 msgid "Pausing the current call..." msgstr "Mise en attente de l'appel..." @@ -1917,7 +1892,7 @@ msgstr "En congé" msgid "Unknown-bug" msgstr "Bug inconnu" -#: ../coreapi/proxy.c:279 +#: ../coreapi/proxy.c:314 msgid "" "The sip proxy address you entered is invalid, it must start with \"sip:\" " "followed by a hostname." @@ -1925,7 +1900,7 @@ msgstr "" "L'adresse SIP du proxy est invalide. Elle doit commencer par \"sip:\" suivie " "par un nom de domaine." -#: ../coreapi/proxy.c:285 +#: ../coreapi/proxy.c:320 msgid "" "The sip identity you entered is invalid.\n" "It should look like sip:username@proxydomain, such as sip:alice@example.net" @@ -1934,131 +1909,156 @@ msgstr "" "Elle doit être de la forme sip:username@domain, comme par example sip:" "alice@example.net" -#: ../coreapi/proxy.c:1299 +#: ../coreapi/proxy.c:1369 #, c-format msgid "Could not login as %s" msgstr "Echec de la connexion en tant que %s" -#: ../coreapi/callbacks.c:354 +#: ../coreapi/callbacks.c:355 msgid "Remote ringing." msgstr "Sonnerie distante." -#: ../coreapi/callbacks.c:370 +#: ../coreapi/callbacks.c:373 msgid "Remote ringing..." msgstr "Sonnerie distante..." -#: ../coreapi/callbacks.c:381 +#: ../coreapi/callbacks.c:384 msgid "Early media." msgstr "Prise d'appel anticipée." -#: ../coreapi/callbacks.c:432 +#: ../coreapi/callbacks.c:435 #, c-format msgid "Call with %s is paused." msgstr "%s est maintenant en attente." -#: ../coreapi/callbacks.c:445 +#: ../coreapi/callbacks.c:448 #, c-format msgid "Call answered by %s - on hold." msgstr "Appel répondu par %s - en attente" -#: ../coreapi/callbacks.c:456 +#: ../coreapi/callbacks.c:459 msgid "Call resumed." msgstr "Appel repris." -#: ../coreapi/callbacks.c:461 +#: ../coreapi/callbacks.c:464 #, c-format msgid "Call answered by %s." msgstr "Appel répondu par %s." -#: ../coreapi/callbacks.c:480 +#: ../coreapi/callbacks.c:483 msgid "Incompatible, check codecs or security settings..." msgstr "" -#: ../coreapi/callbacks.c:531 +#: ../coreapi/callbacks.c:512 msgid "We have been resumed." msgstr "Appel repris." -#: ../coreapi/callbacks.c:541 +#: ../coreapi/callbacks.c:521 msgid "We are paused by other party." msgstr "L'appel a été mis en attente." -#: ../coreapi/callbacks.c:558 +#: ../coreapi/callbacks.c:556 #, fuzzy msgid "Call is updated by remote." msgstr "Mise à jour de l'appel par le correspondant." -#: ../coreapi/callbacks.c:637 +#: ../coreapi/callbacks.c:658 msgid "Call terminated." msgstr "Appel terminé." -#: ../coreapi/callbacks.c:666 +#: ../coreapi/callbacks.c:687 msgid "User is busy." msgstr "Occupé..." -#: ../coreapi/callbacks.c:667 +#: ../coreapi/callbacks.c:688 msgid "User is temporarily unavailable." msgstr "L'usager est temporairement indisponible." #. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:669 +#: ../coreapi/callbacks.c:690 msgid "User does not want to be disturbed." msgstr "L'usager ne souhaite pas être dérangé" -#: ../coreapi/callbacks.c:670 +#: ../coreapi/callbacks.c:691 msgid "Call declined." msgstr "Appel décliné." -#: ../coreapi/callbacks.c:685 +#: ../coreapi/callbacks.c:706 msgid "Request timeout." msgstr "" -#: ../coreapi/callbacks.c:716 +#: ../coreapi/callbacks.c:737 msgid "Redirected" msgstr "Redirection" -#: ../coreapi/callbacks.c:766 +#: ../coreapi/callbacks.c:787 msgid "Incompatible media parameters." msgstr "Paramètres media incompatibles." -#: ../coreapi/callbacks.c:777 +#: ../coreapi/callbacks.c:798 msgid "Call failed." msgstr "L'appel a échoué." -#: ../coreapi/callbacks.c:852 +#: ../coreapi/callbacks.c:878 #, c-format msgid "Registration on %s successful." msgstr "Enregistrement sur %s effectué." -#: ../coreapi/callbacks.c:853 +#: ../coreapi/callbacks.c:879 #, c-format msgid "Unregistration on %s done." msgstr "Désenregistrement sur %s effectué." -#: ../coreapi/callbacks.c:875 +#: ../coreapi/callbacks.c:897 msgid "no response timeout" msgstr "Pas de réponse" -#: ../coreapi/callbacks.c:878 +#: ../coreapi/callbacks.c:900 #, c-format msgid "Registration on %s failed: %s" msgstr "Echec de l'enregistrement sur %s: %s" -#: ../coreapi/callbacks.c:885 +#: ../coreapi/callbacks.c:907 msgid "Service unavailable, retrying" msgstr "" -#: ../coreapi/linphonecall.c:175 +#: ../coreapi/linphonecall.c:177 #, c-format msgid "Authentication token is %s" msgstr "Le jeton d'authentification est %s" -#: ../coreapi/linphonecall.c:2994 +#: ../coreapi/linphonecall.c:2932 #, c-format msgid "You have missed %i call." msgid_plural "You have missed %i calls." msgstr[0] "Vous avez manqué %i appel" msgstr[1] "Vous avez manqué %i appels" +#~ msgid "aborted" +#~ msgstr "abandonné" + +#~ msgid "completed" +#~ msgstr "terminé" + +#~ msgid "missed" +#~ msgstr "manqué" + +#~ msgid "" +#~ "%s at %s\n" +#~ "From: %s\n" +#~ "To: %s\n" +#~ "Status: %s\n" +#~ "Duration: %i mn %i sec\n" +#~ msgstr "" +#~ "%s le %s\n" +#~ "De: %s\n" +#~ "A destination de: %s\n" +#~ "Etat: %s\n" +#~ "Durée: %i mn %i sec\n" + +#~ msgid "Outgoing call" +#~ msgstr "Appel sortant" + #~ msgid "No response." #~ msgstr "Pas de réponse." diff --git a/po/he.po b/po/he.po index 878ac3e4a..f6dd58f14 100644 --- a/po/he.po +++ b/po/he.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Linphone 3.5.99.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-01 21:24+0200\n" +"POT-Creation-Date: 2014-09-15 09:24+0200\n" "PO-Revision-Date: 2013-04-24 21:31+0200\n" "Last-Translator: Isratine Citizen \n" "Language-Team: Rahut Project \n" @@ -20,12 +20,12 @@ msgstr "" "X-Generator: Poedit 1.5.4\n" # צור קשר עם -#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:973 +#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:974 #, c-format msgid "Call %s" msgstr "התקשר אל %s" -#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:974 +#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:975 #, c-format msgid "Send text to %s" msgstr "שלח טקסט אל %s" @@ -35,42 +35,42 @@ msgstr "שלח טקסט אל %s" msgid "Recent calls (%i)" msgstr "שיחות אחרונות (%i)" -#: ../gtk/calllogs.c:312 +#: ../gtk/calllogs.c:314 msgid "n/a" msgstr "לא זמין (n/a)" -#: ../gtk/calllogs.c:315 +#: ../gtk/calllogs.c:317 msgid "Aborted" msgstr "ננטשה" -#: ../gtk/calllogs.c:318 +#: ../gtk/calllogs.c:320 msgid "Missed" msgstr "הוחמצה" -#: ../gtk/calllogs.c:321 +#: ../gtk/calllogs.c:323 msgid "Declined" msgstr "נדחתה" -#: ../gtk/calllogs.c:327 +#: ../gtk/calllogs.c:329 #, c-format msgid "%i minute" msgid_plural "%i minutes" msgstr[0] "דקה %i" msgstr[1] "%i דקות" -#: ../gtk/calllogs.c:330 +#: ../gtk/calllogs.c:332 #, c-format msgid "%i second" msgid_plural "%i seconds" msgstr[0] "שניה %i" msgstr[1] "%i שניות" -#: ../gtk/calllogs.c:333 ../gtk/calllogs.c:339 +#: ../gtk/calllogs.c:335 ../gtk/calllogs.c:341 #, c-format msgid "%s\t%s" msgstr "" -#: ../gtk/calllogs.c:335 +#: ../gtk/calllogs.c:337 #, c-format msgid "" "%s\tQuality: %s\n" @@ -79,7 +79,7 @@ msgstr "" "%s\tאיכות: %s\n" "%s\t%s\t" -#: ../gtk/calllogs.c:341 +#: ../gtk/calllogs.c:343 #, c-format msgid "" "%s\t\n" @@ -100,7 +100,7 @@ msgid "Couldn't find pixmap file: %s" msgstr "לא ניתן למצוא קובץ ‫pixmap: ‫%s" # איש־קשר -#: ../gtk/chat.c:363 ../gtk/friendlist.c:923 +#: ../gtk/chat.c:364 ../gtk/friendlist.c:924 msgid "Invalid sip contact !" msgstr "כתובת sip לא תקפה !" @@ -168,7 +168,7 @@ msgstr "התקשרות באמצעות %s" # הקשר שלהם # אם התשובה -#: ../gtk/main.c:1171 +#: ../gtk/main.c:1183 #, c-format msgid "" "%s would like to add you to his contact list.\n" @@ -181,7 +181,7 @@ msgstr "" "שלך ?\n" "היה ותשובתך תהיה לא, אדם זה יהיה מסומן באופן זמני ברשימה השחורה." -#: ../gtk/main.c:1248 +#: ../gtk/main.c:1260 #, fuzzy, c-format msgid "" "Please enter your password for username %s\n" @@ -191,65 +191,65 @@ msgstr "" " בתחום %s:" # שיחה -#: ../gtk/main.c:1364 +#: ../gtk/main.c:1376 msgid "Call error" msgstr "שגיאת קריאה" # Conversation ended -#: ../gtk/main.c:1367 ../coreapi/linphonecore.c:3515 +#: ../gtk/main.c:1379 ../coreapi/linphonecore.c:3240 msgid "Call ended" msgstr "שיחה הסתיימה" -#: ../gtk/main.c:1370 ../coreapi/linphonecore.c:254 +#: ../gtk/main.c:1382 msgid "Incoming call" msgstr "קריאה נכנסת" -#: ../gtk/main.c:1372 ../gtk/incall_view.c:513 ../gtk/main.ui.h:5 +#: ../gtk/main.c:1384 ../gtk/incall_view.c:522 ../gtk/main.ui.h:5 msgid "Answer" msgstr "לענות" # דחיה -#: ../gtk/main.c:1374 ../gtk/main.ui.h:6 +#: ../gtk/main.c:1386 ../gtk/main.ui.h:6 msgid "Decline" msgstr "לדחות" # Conversation paused -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 msgid "Call paused" msgstr "שיחה הושהתה" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, c-format msgid "by %s" msgstr "על ידי %s" -#: ../gtk/main.c:1447 +#: ../gtk/main.c:1459 #, c-format msgid "%s proposed to start video. Do you accept ?" msgstr "‏%s רוצה להתחיל וידאו. האם אתה מסכים ?" -#: ../gtk/main.c:1609 +#: ../gtk/main.c:1621 msgid "Website link" msgstr "קישור אתר רשת" # ‫Linphone - וידאופון במרשתת -#: ../gtk/main.c:1658 +#: ../gtk/main.c:1670 msgid "Linphone - a video internet phone" msgstr "‫Linphone - וידאופון אינטרנטי" # משתמטת -#: ../gtk/main.c:1750 +#: ../gtk/main.c:1762 #, c-format msgid "%s (Default)" msgstr "‫%s (ברירת מחדל)" -#: ../gtk/main.c:2086 ../coreapi/callbacks.c:927 +#: ../gtk/main.c:2099 ../coreapi/callbacks.c:949 #, c-format msgid "We are transferred to %s" msgstr "אנחנו מועברים אל %s" # קריאות שמע -#: ../gtk/main.c:2096 +#: ../gtk/main.c:2109 msgid "" "No sound cards have been detected on this computer.\n" "You won't be able to send or receive audio calls." @@ -257,7 +257,7 @@ msgstr "" "לא אותרו כרטיסי קול במחשב זה.\n" "לא תהיה ביכולתך לשלוח או לקבל שיחות אודיו." -#: ../gtk/main.c:2237 +#: ../gtk/main.c:2250 msgid "A free SIP video-phone" msgstr "וידאופון SIP חופשי" @@ -269,7 +269,7 @@ msgstr "הוסף אל ספר כתובות" msgid "Presence status" msgstr "מצב נוכחות" -#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:550 ../gtk/contact.ui.h:1 +#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:552 ../gtk/contact.ui.h:1 msgid "Name" msgstr "שם" @@ -287,148 +287,148 @@ msgstr "שיחה" msgid "Search in %s directory" msgstr "חיפוש במדור %s" -#: ../gtk/friendlist.c:975 +#: ../gtk/friendlist.c:976 #, c-format msgid "Edit contact '%s'" msgstr "ערוך איש קשר '%s'" -#: ../gtk/friendlist.c:976 +#: ../gtk/friendlist.c:977 #, c-format msgid "Delete contact '%s'" msgstr "מחק איש קשר '%s'" -#: ../gtk/friendlist.c:977 +#: ../gtk/friendlist.c:978 #, c-format msgid "Delete chat history of '%s'" msgstr "מחק היסטוריית שיחה של '%s'" -#: ../gtk/friendlist.c:1028 +#: ../gtk/friendlist.c:1029 #, c-format msgid "Add new contact from %s directory" msgstr "הוסף איש קשר חדש מן מדור %s" # קצב תדר תדירות מהירות -#: ../gtk/propertybox.c:556 +#: ../gtk/propertybox.c:558 msgid "Rate (Hz)" msgstr "שיעור (הרץ)" -#: ../gtk/propertybox.c:562 +#: ../gtk/propertybox.c:564 msgid "Status" msgstr "מצב" # שיעור סיביות מינימלי -#: ../gtk/propertybox.c:568 +#: ../gtk/propertybox.c:570 #, fuzzy msgid "IP Bitrate (kbit/s)" msgstr "קצב נתונים מינימלי (קי״ב/שנ׳)" -#: ../gtk/propertybox.c:575 +#: ../gtk/propertybox.c:577 msgid "Parameters" msgstr "פרמטרים" # מאופשר -#: ../gtk/propertybox.c:618 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:763 msgid "Enabled" msgstr "מופעל" # מנוטרל -#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:622 ../gtk/propertybox.c:763 msgid "Disabled" msgstr "לא מופעל" -#: ../gtk/propertybox.c:807 +#: ../gtk/propertybox.c:809 msgid "Account" msgstr "חשבון" -#: ../gtk/propertybox.c:1061 +#: ../gtk/propertybox.c:1063 msgid "English" msgstr "English" -#: ../gtk/propertybox.c:1062 +#: ../gtk/propertybox.c:1064 msgid "French" msgstr "Français" -#: ../gtk/propertybox.c:1063 +#: ../gtk/propertybox.c:1065 msgid "Swedish" msgstr "Svenska" -#: ../gtk/propertybox.c:1064 +#: ../gtk/propertybox.c:1066 msgid "Italian" msgstr "Italiano" -#: ../gtk/propertybox.c:1065 +#: ../gtk/propertybox.c:1067 msgid "Spanish" msgstr "Español" # português do Brasil -#: ../gtk/propertybox.c:1066 +#: ../gtk/propertybox.c:1068 msgid "Brazilian Portugese" msgstr "português brasileiro" -#: ../gtk/propertybox.c:1067 +#: ../gtk/propertybox.c:1069 msgid "Polish" msgstr "Polski" -#: ../gtk/propertybox.c:1068 +#: ../gtk/propertybox.c:1070 msgid "German" msgstr "Deutsch" -#: ../gtk/propertybox.c:1069 +#: ../gtk/propertybox.c:1071 msgid "Russian" msgstr "Русский" -#: ../gtk/propertybox.c:1070 +#: ../gtk/propertybox.c:1072 msgid "Japanese" msgstr "日本語" -#: ../gtk/propertybox.c:1071 +#: ../gtk/propertybox.c:1073 msgid "Dutch" msgstr "Nederlands" -#: ../gtk/propertybox.c:1072 +#: ../gtk/propertybox.c:1074 msgid "Hungarian" msgstr "Magyar" -#: ../gtk/propertybox.c:1073 +#: ../gtk/propertybox.c:1075 msgid "Czech" msgstr "Česky" -#: ../gtk/propertybox.c:1074 +#: ../gtk/propertybox.c:1076 msgid "Chinese" msgstr "中文" # 繁体字 -#: ../gtk/propertybox.c:1075 +#: ../gtk/propertybox.c:1077 msgid "Traditional Chinese" msgstr "繁體字" -#: ../gtk/propertybox.c:1076 +#: ../gtk/propertybox.c:1078 msgid "Norwegian" msgstr "norsk" -#: ../gtk/propertybox.c:1077 +#: ../gtk/propertybox.c:1079 msgid "Hebrew" msgstr "עברית" -#: ../gtk/propertybox.c:1078 +#: ../gtk/propertybox.c:1080 msgid "Serbian" msgstr "српски srpski" # selected הנבחרת -#: ../gtk/propertybox.c:1145 +#: ../gtk/propertybox.c:1147 msgid "" "You need to restart linphone for the new language selection to take effect." msgstr "עליך לאתחל את לינפון כדי שהשפה החדשה תיכנס לתוקף." -#: ../gtk/propertybox.c:1223 +#: ../gtk/propertybox.c:1225 msgid "None" msgstr "ללא" -#: ../gtk/propertybox.c:1227 +#: ../gtk/propertybox.c:1229 msgid "SRTP" msgstr "" -#: ../gtk/propertybox.c:1233 +#: ../gtk/propertybox.c:1235 msgid "ZRTP" msgstr "" @@ -502,58 +502,62 @@ msgstr "" msgid "Enter your linphone.org username" msgstr "הזן את שם משתמשך אצל linphone.org" -#: ../gtk/setupwizard.c:96 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 +#: ../gtk/setupwizard.c:102 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 msgid "Username:" msgstr "שם משתמש:" -#: ../gtk/setupwizard.c:98 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 +#: ../gtk/setupwizard.c:104 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 msgid "Password:" msgstr "סיסמה:" -#: ../gtk/setupwizard.c:118 +#: ../gtk/setupwizard.c:124 msgid "Enter your account informations" msgstr "הזן את מידע חשבונך" -#: ../gtk/setupwizard.c:125 +#: ../gtk/setupwizard.c:140 msgid "Username*" msgstr "שם משתמש*" -#: ../gtk/setupwizard.c:126 +#: ../gtk/setupwizard.c:141 msgid "Password*" msgstr "סיסמה*" -#: ../gtk/setupwizard.c:129 +#: ../gtk/setupwizard.c:144 msgid "Domain*" msgstr "מתחם*" -#: ../gtk/setupwizard.c:130 +#: ../gtk/setupwizard.c:145 msgid "Proxy" msgstr "פרוקסי" # נדרשים -#: ../gtk/setupwizard.c:302 +#: ../gtk/setupwizard.c:317 msgid "(*) Required fields" msgstr "(*) שדות חובה" -#: ../gtk/setupwizard.c:303 +#: ../gtk/setupwizard.c:318 msgid "Username: (*)" msgstr "שם משתמש: (*)" -#: ../gtk/setupwizard.c:305 +#: ../gtk/setupwizard.c:320 msgid "Password: (*)" msgstr "סיסמה: (*)" -#: ../gtk/setupwizard.c:307 +#: ../gtk/setupwizard.c:322 msgid "Email: (*)" msgstr "דוא״ל: (*)" -#: ../gtk/setupwizard.c:309 +#: ../gtk/setupwizard.c:324 msgid "Confirm your password: (*)" msgstr "אימות סיסמתך: (*)" +#: ../gtk/setupwizard.c:338 +msgid "Keep me informed with linphone updates" +msgstr "" + # אינו בר־השגה # לשוב אחורה -#: ../gtk/setupwizard.c:373 +#: ../gtk/setupwizard.c:394 msgid "" "Error, account not validated, username already used or server unreachable.\n" "Please go back and try again." @@ -561,12 +565,12 @@ msgstr "" "שגיאה, חשבון לא אומת, שם משתמש כבר בשימוש או שרת לא ניתן להשגה.\n" "נא לחזור ולנסות שוב." -#: ../gtk/setupwizard.c:384 +#: ../gtk/setupwizard.c:405 msgid "Thank you. Your account is now configured and ready for use." msgstr "תודה לך. חשבונך מוגדר ומוכן לשימוש כעת." # לאחר מכן -#: ../gtk/setupwizard.c:392 +#: ../gtk/setupwizard.c:413 msgid "" "Please validate your account by clicking on the link we just sent you by " "email.\n" @@ -575,44 +579,44 @@ msgstr "" "נא לאמת את חשבונך באמצעות הקלקה על הקישור ששלחנו לך עתה באמצעות דוא״ל.\n" "אחרי כן נא לחזור לכאן וללחוץ על הלחצן 'קדימה'." -#: ../gtk/setupwizard.c:564 +#: ../gtk/setupwizard.c:600 #, fuzzy msgid "SIP account configuration assistant" msgstr "אשף הגדרת חשבון" # Wizard אשף # סייע -#: ../gtk/setupwizard.c:582 +#: ../gtk/setupwizard.c:618 msgid "Welcome to the account setup assistant" msgstr "ברוך בואך אל אשף הגדרת החשבון" -#: ../gtk/setupwizard.c:587 +#: ../gtk/setupwizard.c:623 msgid "Account setup assistant" msgstr "אשף הגדרת חשבון" # שלב -#: ../gtk/setupwizard.c:593 +#: ../gtk/setupwizard.c:629 msgid "Configure your account (step 1/1)" msgstr "הגדרת חשבונך (צעד 1/1)" -#: ../gtk/setupwizard.c:598 +#: ../gtk/setupwizard.c:634 msgid "Enter your sip username (step 1/1)" msgstr "הזנת שם משתמש sip (צעד 1/1)" -#: ../gtk/setupwizard.c:602 +#: ../gtk/setupwizard.c:638 msgid "Enter account information (step 1/2)" msgstr "הזנת מידע חשבון (צעד 1/2)" # תקפות -#: ../gtk/setupwizard.c:611 +#: ../gtk/setupwizard.c:647 msgid "Validation (step 2/2)" msgstr "אימות (צעד 2/2)" -#: ../gtk/setupwizard.c:616 +#: ../gtk/setupwizard.c:652 msgid "Error" msgstr "שגיאה" -#: ../gtk/setupwizard.c:620 ../gtk/audio_assistant.c:519 +#: ../gtk/setupwizard.c:656 ../gtk/audio_assistant.c:527 msgid "Terminating" msgstr "מסיים כעת" @@ -678,7 +682,7 @@ msgstr "‏uPnP נכשלה" msgid "Direct or through server" msgstr "ישיר או דרך שרת" -#: ../gtk/incall_view.c:266 ../gtk/incall_view.c:276 +#: ../gtk/incall_view.c:267 ../gtk/incall_view.c:279 #, c-format msgid "" "download: %f\n" @@ -687,122 +691,122 @@ msgstr "" "הורדה: %f\n" "העלאה: %f (קי״ב/שנ׳)" -#: ../gtk/incall_view.c:271 ../gtk/incall_view.c:272 +#: ../gtk/incall_view.c:272 ../gtk/incall_view.c:274 #, c-format -msgid "%ix%i" +msgid "%ix%i @ %f fps" msgstr "" -#: ../gtk/incall_view.c:301 +#: ../gtk/incall_view.c:304 #, c-format msgid "%.3f seconds" msgstr "%.3f שניות" -#: ../gtk/incall_view.c:399 ../gtk/main.ui.h:12 +#: ../gtk/incall_view.c:407 ../gtk/main.ui.h:12 msgid "Hang up" msgstr "נתק" -#: ../gtk/incall_view.c:492 +#: ../gtk/incall_view.c:501 msgid "Calling..." msgstr "מתקשר כעת..." -#: ../gtk/incall_view.c:495 ../gtk/incall_view.c:698 +#: ../gtk/incall_view.c:504 ../gtk/incall_view.c:707 msgid "00::00::00" msgstr "‭00::00::00" -#: ../gtk/incall_view.c:506 +#: ../gtk/incall_view.c:515 msgid "Incoming call" msgstr "קריאה נכנסת" -#: ../gtk/incall_view.c:543 +#: ../gtk/incall_view.c:552 msgid "good" msgstr "טובה" # רגילה -#: ../gtk/incall_view.c:545 +#: ../gtk/incall_view.c:554 msgid "average" msgstr "ממוצעת" # weak חלשה חלושה רפויה רופפת -#: ../gtk/incall_view.c:547 +#: ../gtk/incall_view.c:556 msgid "poor" msgstr "דלה" -#: ../gtk/incall_view.c:549 +#: ../gtk/incall_view.c:558 msgid "very poor" msgstr "דלה מאוד" # רעה -#: ../gtk/incall_view.c:551 +#: ../gtk/incall_view.c:560 msgid "too bad" msgstr "גרועה מדי" -#: ../gtk/incall_view.c:552 ../gtk/incall_view.c:568 +#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:577 msgid "unavailable" msgstr "לא זמינה" # באמצעות -#: ../gtk/incall_view.c:660 +#: ../gtk/incall_view.c:669 msgid "Secured by SRTP" msgstr "מאובטחת על ידי SRTP" -#: ../gtk/incall_view.c:666 +#: ../gtk/incall_view.c:675 #, c-format msgid "Secured by ZRTP - [auth token: %s]" msgstr "מאובטחת על ידי ZRTP - [אות אימות: %s]" # set or unset verification state of ZRTP SAS. -#: ../gtk/incall_view.c:672 +#: ../gtk/incall_view.c:681 msgid "Set unverified" msgstr "הגדר כלא מאומתת" -#: ../gtk/incall_view.c:672 ../gtk/main.ui.h:4 +#: ../gtk/incall_view.c:681 ../gtk/main.ui.h:4 msgid "Set verified" msgstr "הגדר כמאומתת" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In conference" msgstr "בשיחת ועידה" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In call" msgstr "בשיחה כעת" -#: ../gtk/incall_view.c:729 +#: ../gtk/incall_view.c:738 msgid "Paused call" msgstr "שיחה מושהית" # שעות %02i דקות %02i שניות %02i # Force LTR time format (hours::minutes::seconds) with LRO chatacter (U+202D) -#: ../gtk/incall_view.c:742 +#: ../gtk/incall_view.c:751 #, c-format msgid "%02i::%02i::%02i" msgstr "‭%02i::%02i::%02i" -#: ../gtk/incall_view.c:760 +#: ../gtk/incall_view.c:772 msgid "Call ended." msgstr "שיחה הסתיימה." -#: ../gtk/incall_view.c:791 +#: ../gtk/incall_view.c:803 msgid "Transfer in progress" msgstr "העברה מצויה כעת בעיצומה" -#: ../gtk/incall_view.c:794 +#: ../gtk/incall_view.c:806 msgid "Transfer done." msgstr "העברה הסתיימה." -#: ../gtk/incall_view.c:797 +#: ../gtk/incall_view.c:809 msgid "Transfer failed." msgstr "העברה נכשלה." -#: ../gtk/incall_view.c:841 +#: ../gtk/incall_view.c:853 msgid "Resume" msgstr "חזור" -#: ../gtk/incall_view.c:848 ../gtk/main.ui.h:9 +#: ../gtk/incall_view.c:860 ../gtk/main.ui.h:9 msgid "Pause" msgstr "השהה" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, c-format msgid "" "Recording into\n" @@ -811,7 +815,7 @@ msgstr "" "מקליט אל תוך\n" "%s %s" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 msgid "(Paused)" msgstr "(מושהה)" @@ -846,7 +850,7 @@ msgstr "" msgid "Too loud" msgstr "" -#: ../gtk/audio_assistant.c:316 +#: ../gtk/audio_assistant.c:318 #, fuzzy msgid "" "Welcome !\n" @@ -855,59 +859,59 @@ msgstr "" "ברוך בואך !\n" "אשף זה יסייע לך לעשות שימוש בחשבון SIP עבור שיחותייך." -#: ../gtk/audio_assistant.c:326 +#: ../gtk/audio_assistant.c:328 #, fuzzy msgid "Capture device" msgstr "התקן לכידה:" -#: ../gtk/audio_assistant.c:327 +#: ../gtk/audio_assistant.c:329 msgid "Recorded volume" msgstr "" -#: ../gtk/audio_assistant.c:331 +#: ../gtk/audio_assistant.c:333 msgid "No voice" msgstr "" -#: ../gtk/audio_assistant.c:367 +#: ../gtk/audio_assistant.c:369 #, fuzzy msgid "Playback device" msgstr "התקן פס קול:" -#: ../gtk/audio_assistant.c:368 +#: ../gtk/audio_assistant.c:370 msgid "Play three beeps" msgstr "" -#: ../gtk/audio_assistant.c:400 +#: ../gtk/audio_assistant.c:403 msgid "Press the record button and say some words" msgstr "" -#: ../gtk/audio_assistant.c:401 +#: ../gtk/audio_assistant.c:404 msgid "Listen to your record voice" msgstr "" -#: ../gtk/audio_assistant.c:430 +#: ../gtk/audio_assistant.c:433 msgid "Let's start Linphone now" msgstr "" -#: ../gtk/audio_assistant.c:488 +#: ../gtk/audio_assistant.c:496 #, fuzzy msgid "Audio Assistant" msgstr "אשף חשבון" -#: ../gtk/audio_assistant.c:498 ../gtk/main.ui.h:31 +#: ../gtk/audio_assistant.c:506 ../gtk/main.ui.h:31 #, fuzzy msgid "Audio assistant" msgstr "אשף חשבון" -#: ../gtk/audio_assistant.c:503 +#: ../gtk/audio_assistant.c:511 msgid "Mic Gain calibration" msgstr "" -#: ../gtk/audio_assistant.c:509 +#: ../gtk/audio_assistant.c:517 msgid "Speaker volume calibration" msgstr "" -#: ../gtk/audio_assistant.c:514 +#: ../gtk/audio_assistant.c:522 msgid "Record and Play" msgstr "" @@ -1872,100 +1876,68 @@ msgstr "מתחבר כעת..." msgid "Please wait while fetching configuration from server..." msgstr "" -#: ../coreapi/linphonecore.c:242 -msgid "aborted" -msgstr "ננטשה" - -#: ../coreapi/linphonecore.c:245 -msgid "completed" -msgstr "הסתיימה" - -#: ../coreapi/linphonecore.c:248 -msgid "missed" -msgstr "הוחמצה" - -# needs to be tested -#: ../coreapi/linphonecore.c:253 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" -"%s אצל %s\n" -"מאת: %s\n" -"אל: %s\n" -"מצב: %s\n" -"משך: %i mn %i sec\n" - -#: ../coreapi/linphonecore.c:254 -msgid "Outgoing call" -msgstr "קריאה יוצאת" - -#: ../coreapi/linphonecore.c:1287 +#: ../coreapi/linphonecore.c:1034 msgid "Ready" msgstr "מוכן" # וידוא -#: ../coreapi/linphonecore.c:2248 +#: ../coreapi/linphonecore.c:1967 #, fuzzy msgid "Configuring" msgstr "אימות" -#: ../coreapi/linphonecore.c:2410 +#: ../coreapi/linphonecore.c:2133 msgid "Looking for telephone number destination..." msgstr "מחפש כעת עבור יעד מספר טלפון..." -#: ../coreapi/linphonecore.c:2413 +#: ../coreapi/linphonecore.c:2136 msgid "Could not resolve this number." msgstr "לא ניתן לפתור את מספר זה." #. must be known at that time -#: ../coreapi/linphonecore.c:2695 +#: ../coreapi/linphonecore.c:2418 msgid "Contacting" msgstr "מתקשר כעת" -#: ../coreapi/linphonecore.c:2702 +#: ../coreapi/linphonecore.c:2425 msgid "Could not call" msgstr "לא ניתן להתקשר" # מספר השיחות המקבילות המרבי -#: ../coreapi/linphonecore.c:2852 +#: ../coreapi/linphonecore.c:2576 msgid "Sorry, we have reached the maximum number of simultaneous calls" msgstr "הגענו אל המספר המרבי של שיחות מקבילות, עמך הסליחה" -#: ../coreapi/linphonecore.c:3022 +#: ../coreapi/linphonecore.c:2745 msgid "is contacting you" msgstr "מתקשר/ת אליך" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid " and asked autoanswer." msgstr " ומבקש/ת מענה אוטומטי." -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid "." msgstr "" # פרמטרי קריאה -#: ../coreapi/linphonecore.c:3139 +#: ../coreapi/linphonecore.c:2865 msgid "Modifying call parameters..." msgstr "מתאים כעת פרמטרים של שיחה..." -#: ../coreapi/linphonecore.c:3469 +#: ../coreapi/linphonecore.c:3194 msgid "Connected." msgstr "מקושר." -#: ../coreapi/linphonecore.c:3495 +#: ../coreapi/linphonecore.c:3220 msgid "Call aborted" msgstr "קריאה בוטלה" -#: ../coreapi/linphonecore.c:3685 +#: ../coreapi/linphonecore.c:3412 msgid "Could not pause the call" msgstr "לא ניתן להשהות את השיחה" -#: ../coreapi/linphonecore.c:3690 +#: ../coreapi/linphonecore.c:3417 msgid "Pausing the current call..." msgstr "משהה כעת שיחה נוכחית..." @@ -2036,7 +2008,7 @@ msgstr "משך זמן" msgid "Unknown-bug" msgstr "תקלה לא מוכרת" -#: ../coreapi/proxy.c:279 +#: ../coreapi/proxy.c:314 msgid "" "The sip proxy address you entered is invalid, it must start with \"sip:\" " "followed by a hostname." @@ -2044,7 +2016,7 @@ msgstr "" "כתובת sip proxy שהזנת הינה שגויה, זו צריכה להתחיל עם‭\"sip:\" ‬ לאחר שם מארח." # כמו למשל -#: ../coreapi/proxy.c:285 +#: ../coreapi/proxy.c:320 msgid "" "The sip identity you entered is invalid.\n" "It should look like sip:username@proxydomain, such as sip:alice@example.net" @@ -2053,40 +2025,40 @@ msgstr "" "זו צריכה להיראות כמו sip:username@proxydomain, למשל sip:alice@example.net" # בשם כ־ -#: ../coreapi/proxy.c:1299 +#: ../coreapi/proxy.c:1369 #, c-format msgid "Could not login as %s" msgstr "לא ניתן להתחבר בזהות %s" -#: ../coreapi/callbacks.c:354 +#: ../coreapi/callbacks.c:355 msgid "Remote ringing." msgstr "צלצול מרוחק." -#: ../coreapi/callbacks.c:370 +#: ../coreapi/callbacks.c:373 msgid "Remote ringing..." msgstr "צלצול מרוחק..." # A SIP state -#: ../coreapi/callbacks.c:381 +#: ../coreapi/callbacks.c:384 msgid "Early media." msgstr "מדיה מוקדמת." -#: ../coreapi/callbacks.c:432 +#: ../coreapi/callbacks.c:435 #, c-format msgid "Call with %s is paused." msgstr "שיחה עם %s מושהית." -#: ../coreapi/callbacks.c:445 +#: ../coreapi/callbacks.c:448 #, c-format msgid "Call answered by %s - on hold." msgstr "קריאה נענתה על ידי %s - בהמתנה." # renewed -#: ../coreapi/callbacks.c:456 +#: ../coreapi/callbacks.c:459 msgid "Call resumed." msgstr "קריאה חודשה." -#: ../coreapi/callbacks.c:461 +#: ../coreapi/callbacks.c:464 #, c-format msgid "Call answered by %s." msgstr "קריאה נענתה על ידי %s." @@ -2094,102 +2066,128 @@ msgstr "קריאה נענתה על ידי %s." # לא תואם # אי תאימות # אי התאמה -#: ../coreapi/callbacks.c:480 +#: ../coreapi/callbacks.c:483 msgid "Incompatible, check codecs or security settings..." msgstr "חוסר תאימות, בדוק קודקים או הגדרות אבטחה..." -#: ../coreapi/callbacks.c:531 +#: ../coreapi/callbacks.c:512 msgid "We have been resumed." msgstr "חזרנו." -#: ../coreapi/callbacks.c:541 +#: ../coreapi/callbacks.c:521 msgid "We are paused by other party." msgstr "אנו מושהים על ידי צד אחר." # באופן מרוחק -#: ../coreapi/callbacks.c:558 +#: ../coreapi/callbacks.c:556 msgid "Call is updated by remote." msgstr "שיחה עודכנה מרחוק." -#: ../coreapi/callbacks.c:637 +#: ../coreapi/callbacks.c:658 msgid "Call terminated." msgstr "קריאה הסתיימה." -#: ../coreapi/callbacks.c:666 +#: ../coreapi/callbacks.c:687 msgid "User is busy." msgstr "משתמש עסוק כעת." -#: ../coreapi/callbacks.c:667 +#: ../coreapi/callbacks.c:688 msgid "User is temporarily unavailable." msgstr "משתמש לא זמין זמנית." #. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:669 +#: ../coreapi/callbacks.c:690 msgid "User does not want to be disturbed." msgstr "משתמש לא מעוניין שיפריעו לו." -#: ../coreapi/callbacks.c:670 +#: ../coreapi/callbacks.c:691 msgid "Call declined." msgstr "קריאה סורבה." -#: ../coreapi/callbacks.c:685 +#: ../coreapi/callbacks.c:706 msgid "Request timeout." msgstr "" -#: ../coreapi/callbacks.c:716 +#: ../coreapi/callbacks.c:737 msgid "Redirected" msgstr "מכוון מחדש" # לא תואם # אי תאימות # אי התאמה -#: ../coreapi/callbacks.c:766 +#: ../coreapi/callbacks.c:787 msgid "Incompatible media parameters." msgstr "פרמטריי מדיה חסרי תואמים." -#: ../coreapi/callbacks.c:777 +#: ../coreapi/callbacks.c:798 msgid "Call failed." msgstr "קריאה נכשלה." # הרשמה אצל %s הושלמה בהצלחה. -#: ../coreapi/callbacks.c:852 +#: ../coreapi/callbacks.c:878 #, c-format msgid "Registration on %s successful." msgstr "רישום אצל %s הושלם בהצלחה." -#: ../coreapi/callbacks.c:853 +#: ../coreapi/callbacks.c:879 #, c-format msgid "Unregistration on %s done." msgstr "אי רישום אצל %s סוים." # Pas de réponse # no response in defined time -#: ../coreapi/callbacks.c:875 +#: ../coreapi/callbacks.c:897 msgid "no response timeout" msgstr "אין היענות תוך זמן מוגדר" -#: ../coreapi/callbacks.c:878 +#: ../coreapi/callbacks.c:900 #, c-format msgid "Registration on %s failed: %s" msgstr "רישום אצל %s נכשל: %s" -#: ../coreapi/callbacks.c:885 +#: ../coreapi/callbacks.c:907 msgid "Service unavailable, retrying" msgstr "" -#: ../coreapi/linphonecall.c:175 +#: ../coreapi/linphonecall.c:177 #, c-format msgid "Authentication token is %s" msgstr "אות האימות הינה %s" # האם כדאי לחקות את הטלפונים הניידים? שיחות של נענו -#: ../coreapi/linphonecall.c:2994 +#: ../coreapi/linphonecall.c:2932 #, c-format msgid "You have missed %i call." msgid_plural "You have missed %i calls." msgstr[0] "החמצת שיחה %i." msgstr[1] "החמצת %i שיחות." +#~ msgid "aborted" +#~ msgstr "ננטשה" + +#~ msgid "completed" +#~ msgstr "הסתיימה" + +#~ msgid "missed" +#~ msgstr "הוחמצה" + +# needs to be tested +#~ msgid "" +#~ "%s at %s\n" +#~ "From: %s\n" +#~ "To: %s\n" +#~ "Status: %s\n" +#~ "Duration: %i mn %i sec\n" +#~ msgstr "" +#~ "%s אצל %s\n" +#~ "מאת: %s\n" +#~ "אל: %s\n" +#~ "מצב: %s\n" +#~ "משך: %i mn %i sec\n" + +#~ msgid "Outgoing call" +#~ msgstr "קריאה יוצאת" + #~ msgid "No response." #~ msgstr "אין תגובה." diff --git a/po/hu.po b/po/hu.po index d69f7e8bc..86c3032b5 100644 --- a/po/hu.po +++ b/po/hu.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: Linphone\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-01 21:24+0200\n" +"POT-Creation-Date: 2014-09-15 09:24+0200\n" "PO-Revision-Date: 2013-03-26 19:00+0100\n" "Last-Translator: Viktor \n" "Language-Team: \n" @@ -17,12 +17,12 @@ msgstr "" "X-Generator: Poedit 1.5.4\n" "Plural-Forms: nplurals=1; plural=1 == 1 ? 0 : 1;\n" -#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:973 +#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:974 #, c-format msgid "Call %s" msgstr "%s hívása" -#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:974 +#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:975 #, c-format msgid "Send text to %s" msgstr "Szöveg küldése a következőnek: %s" @@ -32,42 +32,42 @@ msgstr "Szöveg küldése a következőnek: %s" msgid "Recent calls (%i)" msgstr "vonalban" -#: ../gtk/calllogs.c:312 +#: ../gtk/calllogs.c:314 msgid "n/a" msgstr "-" -#: ../gtk/calllogs.c:315 +#: ../gtk/calllogs.c:317 msgid "Aborted" msgstr "Megszakítva" -#: ../gtk/calllogs.c:318 +#: ../gtk/calllogs.c:320 msgid "Missed" msgstr "Nem fogadott" -#: ../gtk/calllogs.c:321 +#: ../gtk/calllogs.c:323 msgid "Declined" msgstr "Elutasítva" -#: ../gtk/calllogs.c:327 +#: ../gtk/calllogs.c:329 #, c-format msgid "%i minute" msgid_plural "%i minutes" msgstr[0] "%i perc" -#: ../gtk/calllogs.c:330 +#: ../gtk/calllogs.c:332 #, c-format msgid "%i second" msgid_plural "%i seconds" msgstr[0] "%i másodperc" -#: ../gtk/calllogs.c:333 ../gtk/calllogs.c:339 +#: ../gtk/calllogs.c:335 ../gtk/calllogs.c:341 #, fuzzy, c-format msgid "%s\t%s" msgstr "" "%s\t%s\t\n" "%s\t%s" -#: ../gtk/calllogs.c:335 +#: ../gtk/calllogs.c:337 #, fuzzy, c-format msgid "" "%s\tQuality: %s\n" @@ -76,7 +76,7 @@ msgstr "" "%s\t%s\tMinőség: %s\n" "%s\t%s %s\t" -#: ../gtk/calllogs.c:341 +#: ../gtk/calllogs.c:343 #, fuzzy, c-format msgid "" "%s\t\n" @@ -98,7 +98,7 @@ msgstr "én" msgid "Couldn't find pixmap file: %s" msgstr "Nemtalálható a pixmap fájl: %s" -#: ../gtk/chat.c:363 ../gtk/friendlist.c:923 +#: ../gtk/chat.c:364 ../gtk/friendlist.c:924 msgid "Invalid sip contact !" msgstr "Érvénytelen sip partner !" @@ -149,7 +149,7 @@ msgstr "Fiók beállítása varázsló" msgid "Call with %s" msgstr "Hívás %s -el" -#: ../gtk/main.c:1171 +#: ../gtk/main.c:1183 #, c-format msgid "" "%s would like to add you to his contact list.\n" @@ -162,7 +162,7 @@ msgstr "" "szeretné adni a partnerlistához?\n" "Ha nemmel válaszol, ez a személy átmenetileg tiltólistára kerül." -#: ../gtk/main.c:1248 +#: ../gtk/main.c:1260 #, fuzzy, c-format msgid "" "Please enter your password for username %s\n" @@ -171,59 +171,59 @@ msgstr "" "Kérem, adja meg jelszavát a következő felhasználónévhez: %s\n" "tartomány %s:" -#: ../gtk/main.c:1364 +#: ../gtk/main.c:1376 msgid "Call error" msgstr "Hiba a hívás közben" -#: ../gtk/main.c:1367 ../coreapi/linphonecore.c:3515 +#: ../gtk/main.c:1379 ../coreapi/linphonecore.c:3240 msgid "Call ended" msgstr "Hívás vége" -#: ../gtk/main.c:1370 ../coreapi/linphonecore.c:254 +#: ../gtk/main.c:1382 msgid "Incoming call" msgstr "Beérkező hívás" -#: ../gtk/main.c:1372 ../gtk/incall_view.c:513 ../gtk/main.ui.h:5 +#: ../gtk/main.c:1384 ../gtk/incall_view.c:522 ../gtk/main.ui.h:5 msgid "Answer" msgstr "Hívás fogadása" -#: ../gtk/main.c:1374 ../gtk/main.ui.h:6 +#: ../gtk/main.c:1386 ../gtk/main.ui.h:6 msgid "Decline" msgstr "Elutasítás" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 msgid "Call paused" msgstr "Hívás várakoztatva" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, c-format msgid "by %s" msgstr "a következő által: %s" -#: ../gtk/main.c:1447 +#: ../gtk/main.c:1459 #, c-format msgid "%s proposed to start video. Do you accept ?" msgstr "%s szerené elidítani a videót. Elfogadja?" -#: ../gtk/main.c:1609 +#: ../gtk/main.c:1621 msgid "Website link" msgstr "Internetes oldal" -#: ../gtk/main.c:1658 +#: ../gtk/main.c:1670 msgid "Linphone - a video internet phone" msgstr "Linphone - internetes videó telefon" -#: ../gtk/main.c:1750 +#: ../gtk/main.c:1762 #, c-format msgid "%s (Default)" msgstr "%s (Alapértelmezett)" -#: ../gtk/main.c:2086 ../coreapi/callbacks.c:927 +#: ../gtk/main.c:2099 ../coreapi/callbacks.c:949 #, c-format msgid "We are transferred to %s" msgstr "Át vagyunk irányítva ide: %s" -#: ../gtk/main.c:2096 +#: ../gtk/main.c:2109 msgid "" "No sound cards have been detected on this computer.\n" "You won't be able to send or receive audio calls." @@ -231,7 +231,7 @@ msgstr "" "Hangkártya nincs érzékelve ezen a számítógépen.\n" "Nem fog tudni hang hívásokat küldeni vagy fogadni." -#: ../gtk/main.c:2237 +#: ../gtk/main.c:2250 msgid "A free SIP video-phone" msgstr "Egy ingyenes SIP video-telefon" @@ -243,7 +243,7 @@ msgstr "Hozzáadás címjegyzékhez" msgid "Presence status" msgstr "Jelenlét státusz" -#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:550 ../gtk/contact.ui.h:1 +#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:552 ../gtk/contact.ui.h:1 msgid "Name" msgstr "Név" @@ -260,143 +260,143 @@ msgstr "Csevegés" msgid "Search in %s directory" msgstr "Keresés ebben a könyvtárban: %s" -#: ../gtk/friendlist.c:975 +#: ../gtk/friendlist.c:976 #, c-format msgid "Edit contact '%s'" msgstr "Kapcsolatinformációk szerkesztése: '%s'" -#: ../gtk/friendlist.c:976 +#: ../gtk/friendlist.c:977 #, c-format msgid "Delete contact '%s'" msgstr "'%s' partner törlése" -#: ../gtk/friendlist.c:977 +#: ../gtk/friendlist.c:978 #, fuzzy, c-format msgid "Delete chat history of '%s'" msgstr "'%s' partner törlése" -#: ../gtk/friendlist.c:1028 +#: ../gtk/friendlist.c:1029 #, c-format msgid "Add new contact from %s directory" msgstr "Új partner hozzáadása ebből a könyvtárból: %s" -#: ../gtk/propertybox.c:556 +#: ../gtk/propertybox.c:558 msgid "Rate (Hz)" msgstr "Érték (Hz)" -#: ../gtk/propertybox.c:562 +#: ../gtk/propertybox.c:564 msgid "Status" msgstr "Állapot" -#: ../gtk/propertybox.c:568 +#: ../gtk/propertybox.c:570 #, fuzzy msgid "IP Bitrate (kbit/s)" msgstr "Min bitrate (kbit/s)" -#: ../gtk/propertybox.c:575 +#: ../gtk/propertybox.c:577 msgid "Parameters" msgstr "Paraméterek" -#: ../gtk/propertybox.c:618 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:763 msgid "Enabled" msgstr "Engedélyezve" -#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:622 ../gtk/propertybox.c:763 msgid "Disabled" msgstr "Tiltva" -#: ../gtk/propertybox.c:807 +#: ../gtk/propertybox.c:809 msgid "Account" msgstr "Hozzáférés" -#: ../gtk/propertybox.c:1061 +#: ../gtk/propertybox.c:1063 msgid "English" msgstr "angol" -#: ../gtk/propertybox.c:1062 +#: ../gtk/propertybox.c:1064 msgid "French" msgstr "francia" -#: ../gtk/propertybox.c:1063 +#: ../gtk/propertybox.c:1065 msgid "Swedish" msgstr "svéd" -#: ../gtk/propertybox.c:1064 +#: ../gtk/propertybox.c:1066 msgid "Italian" msgstr "olasz" -#: ../gtk/propertybox.c:1065 +#: ../gtk/propertybox.c:1067 msgid "Spanish" msgstr "spanyol" -#: ../gtk/propertybox.c:1066 +#: ../gtk/propertybox.c:1068 msgid "Brazilian Portugese" msgstr "brazil-portugál" -#: ../gtk/propertybox.c:1067 +#: ../gtk/propertybox.c:1069 msgid "Polish" msgstr "lengyel" -#: ../gtk/propertybox.c:1068 +#: ../gtk/propertybox.c:1070 msgid "German" msgstr "német" -#: ../gtk/propertybox.c:1069 +#: ../gtk/propertybox.c:1071 msgid "Russian" msgstr "orosz" -#: ../gtk/propertybox.c:1070 +#: ../gtk/propertybox.c:1072 msgid "Japanese" msgstr "japán" -#: ../gtk/propertybox.c:1071 +#: ../gtk/propertybox.c:1073 msgid "Dutch" msgstr "holland" -#: ../gtk/propertybox.c:1072 +#: ../gtk/propertybox.c:1074 msgid "Hungarian" msgstr "magyar" -#: ../gtk/propertybox.c:1073 +#: ../gtk/propertybox.c:1075 msgid "Czech" msgstr "cseh" -#: ../gtk/propertybox.c:1074 +#: ../gtk/propertybox.c:1076 msgid "Chinese" msgstr "egyszerúsített kínai" -#: ../gtk/propertybox.c:1075 +#: ../gtk/propertybox.c:1077 msgid "Traditional Chinese" msgstr "tradícionális kínai" -#: ../gtk/propertybox.c:1076 +#: ../gtk/propertybox.c:1078 msgid "Norwegian" msgstr "norvég" -#: ../gtk/propertybox.c:1077 +#: ../gtk/propertybox.c:1079 msgid "Hebrew" msgstr "héber" -#: ../gtk/propertybox.c:1078 +#: ../gtk/propertybox.c:1080 msgid "Serbian" msgstr "" -#: ../gtk/propertybox.c:1145 +#: ../gtk/propertybox.c:1147 msgid "" "You need to restart linphone for the new language selection to take effect." msgstr "" "Újra kell indítania a linphone-t, hogy az új nyelv kiválasztása érvényre " "jusson. " -#: ../gtk/propertybox.c:1223 +#: ../gtk/propertybox.c:1225 msgid "None" msgstr "Nincs" -#: ../gtk/propertybox.c:1227 +#: ../gtk/propertybox.c:1229 msgid "SRTP" msgstr "SRTP" -#: ../gtk/propertybox.c:1233 +#: ../gtk/propertybox.c:1235 msgid "ZRTP" msgstr "ZRTP" @@ -467,55 +467,59 @@ msgstr "" msgid "Enter your linphone.org username" msgstr "Adja meg linphone.org felhasználónevét" -#: ../gtk/setupwizard.c:96 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 +#: ../gtk/setupwizard.c:102 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 msgid "Username:" msgstr "Felhasználónév:" -#: ../gtk/setupwizard.c:98 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 +#: ../gtk/setupwizard.c:104 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 msgid "Password:" msgstr "Jelszó:" -#: ../gtk/setupwizard.c:118 +#: ../gtk/setupwizard.c:124 msgid "Enter your account informations" msgstr "Írja be fiókinformációit" -#: ../gtk/setupwizard.c:125 +#: ../gtk/setupwizard.c:140 msgid "Username*" msgstr "Felhasználónév*" -#: ../gtk/setupwizard.c:126 +#: ../gtk/setupwizard.c:141 msgid "Password*" msgstr "Jelszó*" -#: ../gtk/setupwizard.c:129 +#: ../gtk/setupwizard.c:144 msgid "Domain*" msgstr "Tartomány" -#: ../gtk/setupwizard.c:130 +#: ../gtk/setupwizard.c:145 msgid "Proxy" msgstr "Proxy" -#: ../gtk/setupwizard.c:302 +#: ../gtk/setupwizard.c:317 msgid "(*) Required fields" msgstr "(*) Mező kitöltése szükséges" -#: ../gtk/setupwizard.c:303 +#: ../gtk/setupwizard.c:318 msgid "Username: (*)" msgstr "Felhasználónév: (*)" -#: ../gtk/setupwizard.c:305 +#: ../gtk/setupwizard.c:320 msgid "Password: (*)" msgstr "Jelszó: (*)" -#: ../gtk/setupwizard.c:307 +#: ../gtk/setupwizard.c:322 msgid "Email: (*)" msgstr "E-mail: (*)" -#: ../gtk/setupwizard.c:309 +#: ../gtk/setupwizard.c:324 msgid "Confirm your password: (*)" msgstr "Jelszó megerősítése: (*)" -#: ../gtk/setupwizard.c:373 +#: ../gtk/setupwizard.c:338 +msgid "Keep me informed with linphone updates" +msgstr "" + +#: ../gtk/setupwizard.c:394 msgid "" "Error, account not validated, username already used or server unreachable.\n" "Please go back and try again." @@ -524,11 +528,11 @@ msgstr "" "vagy a kiszolgáló nem elérhető.\n" "Kérjük, lépjen vissza és próbálja újra." -#: ../gtk/setupwizard.c:384 +#: ../gtk/setupwizard.c:405 msgid "Thank you. Your account is now configured and ready for use." msgstr "Köszönjük! Az Ön fiókját beállítottuk és használatra kész." -#: ../gtk/setupwizard.c:392 +#: ../gtk/setupwizard.c:413 msgid "" "Please validate your account by clicking on the link we just sent you by " "email.\n" @@ -538,40 +542,40 @@ msgstr "" "hivatkozásra kattintva.\n" "Azután térjen vissza ide és kattintson a Következő gombra." -#: ../gtk/setupwizard.c:564 +#: ../gtk/setupwizard.c:600 #, fuzzy msgid "SIP account configuration assistant" msgstr "Fiók beállítása varázsló" -#: ../gtk/setupwizard.c:582 +#: ../gtk/setupwizard.c:618 msgid "Welcome to the account setup assistant" msgstr "A fiók beállítása varázsló üdvözli Önt" -#: ../gtk/setupwizard.c:587 +#: ../gtk/setupwizard.c:623 msgid "Account setup assistant" msgstr "Fiók beállítása varázsló" -#: ../gtk/setupwizard.c:593 +#: ../gtk/setupwizard.c:629 msgid "Configure your account (step 1/1)" msgstr "Az Ön fiókjának beállítása (1/1 lépés)" -#: ../gtk/setupwizard.c:598 +#: ../gtk/setupwizard.c:634 msgid "Enter your sip username (step 1/1)" msgstr "Adja meg sip felhasználónevét (1/2 lépés)" -#: ../gtk/setupwizard.c:602 +#: ../gtk/setupwizard.c:638 msgid "Enter account information (step 1/2)" msgstr "Adja meg a fiókinformációt (1/2 lépés)" -#: ../gtk/setupwizard.c:611 +#: ../gtk/setupwizard.c:647 msgid "Validation (step 2/2)" msgstr "Érvényesítés (2/2 lépés)" -#: ../gtk/setupwizard.c:616 +#: ../gtk/setupwizard.c:652 msgid "Error" msgstr "Hiba" -#: ../gtk/setupwizard.c:620 ../gtk/audio_assistant.c:519 +#: ../gtk/setupwizard.c:656 ../gtk/audio_assistant.c:527 msgid "Terminating" msgstr "Befejezés" @@ -637,7 +641,7 @@ msgstr "uPnP nem sikerült" msgid "Direct or through server" msgstr "közvetlen vagy kiszolgálón keresztül" -#: ../gtk/incall_view.c:266 ../gtk/incall_view.c:276 +#: ../gtk/incall_view.c:267 ../gtk/incall_view.c:279 #, c-format msgid "" "download: %f\n" @@ -646,115 +650,115 @@ msgstr "" "letöltés: %f\n" "feltöltés: %f (kbit/mp)" -#: ../gtk/incall_view.c:271 ../gtk/incall_view.c:272 +#: ../gtk/incall_view.c:272 ../gtk/incall_view.c:274 #, c-format -msgid "%ix%i" +msgid "%ix%i @ %f fps" msgstr "" -#: ../gtk/incall_view.c:301 +#: ../gtk/incall_view.c:304 #, c-format msgid "%.3f seconds" msgstr "%.3f másodperc" -#: ../gtk/incall_view.c:399 ../gtk/main.ui.h:12 +#: ../gtk/incall_view.c:407 ../gtk/main.ui.h:12 msgid "Hang up" msgstr "Befejezés" -#: ../gtk/incall_view.c:492 +#: ../gtk/incall_view.c:501 msgid "Calling..." msgstr "Hívás folyamatban..." -#: ../gtk/incall_view.c:495 ../gtk/incall_view.c:698 +#: ../gtk/incall_view.c:504 ../gtk/incall_view.c:707 msgid "00::00::00" msgstr "00::00::00" -#: ../gtk/incall_view.c:506 +#: ../gtk/incall_view.c:515 msgid "Incoming call" msgstr "Beérkező hívás" -#: ../gtk/incall_view.c:543 +#: ../gtk/incall_view.c:552 msgid "good" msgstr "jó" -#: ../gtk/incall_view.c:545 +#: ../gtk/incall_view.c:554 msgid "average" msgstr "közepes" -#: ../gtk/incall_view.c:547 +#: ../gtk/incall_view.c:556 msgid "poor" msgstr "gyenge" -#: ../gtk/incall_view.c:549 +#: ../gtk/incall_view.c:558 msgid "very poor" msgstr "nagyon gyenge" -#: ../gtk/incall_view.c:551 +#: ../gtk/incall_view.c:560 msgid "too bad" msgstr "rossz" -#: ../gtk/incall_view.c:552 ../gtk/incall_view.c:568 +#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:577 msgid "unavailable" msgstr "nem elérhető" -#: ../gtk/incall_view.c:660 +#: ../gtk/incall_view.c:669 msgid "Secured by SRTP" msgstr "SRTP-vel titkosítva" -#: ../gtk/incall_view.c:666 +#: ../gtk/incall_view.c:675 #, c-format msgid "Secured by ZRTP - [auth token: %s]" msgstr "ZRTP-vel titkosítva - [hitelesítési jel: %s]" -#: ../gtk/incall_view.c:672 +#: ../gtk/incall_view.c:681 msgid "Set unverified" msgstr "Beállítás ellenőrizetlenként" -#: ../gtk/incall_view.c:672 ../gtk/main.ui.h:4 +#: ../gtk/incall_view.c:681 ../gtk/main.ui.h:4 msgid "Set verified" msgstr "Beállítás ellenőrzöttként" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In conference" msgstr "Konferencián" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In call" msgstr "vonalban" -#: ../gtk/incall_view.c:729 +#: ../gtk/incall_view.c:738 msgid "Paused call" msgstr "Várakoztatott hívás" -#: ../gtk/incall_view.c:742 +#: ../gtk/incall_view.c:751 #, c-format msgid "%02i::%02i::%02i" msgstr "%02i::%02i::%02i" -#: ../gtk/incall_view.c:760 +#: ../gtk/incall_view.c:772 msgid "Call ended." msgstr "Hívás vége." -#: ../gtk/incall_view.c:791 +#: ../gtk/incall_view.c:803 msgid "Transfer in progress" msgstr "Átvitel folyamatban" -#: ../gtk/incall_view.c:794 +#: ../gtk/incall_view.c:806 msgid "Transfer done." msgstr "Átvitel befejezve." -#: ../gtk/incall_view.c:797 +#: ../gtk/incall_view.c:809 msgid "Transfer failed." msgstr "Az átvitel sikertelen." -#: ../gtk/incall_view.c:841 +#: ../gtk/incall_view.c:853 msgid "Resume" msgstr "Visszatérés" -#: ../gtk/incall_view.c:848 ../gtk/main.ui.h:9 +#: ../gtk/incall_view.c:860 ../gtk/main.ui.h:9 msgid "Pause" msgstr "Várakoztatás" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, c-format msgid "" "Recording into\n" @@ -763,7 +767,7 @@ msgstr "" "Felvétel a következőbe\n" "%s %s" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 msgid "(Paused)" msgstr "(Várakoztatva)" @@ -798,7 +802,7 @@ msgstr "" msgid "Too loud" msgstr "" -#: ../gtk/audio_assistant.c:316 +#: ../gtk/audio_assistant.c:318 #, fuzzy msgid "" "Welcome !\n" @@ -807,60 +811,60 @@ msgstr "" "Üdvözöljük !\n" "Ez a varázsló segít Önnek, hogy sip fiókot használjon hívásaihoz." -#: ../gtk/audio_assistant.c:326 +#: ../gtk/audio_assistant.c:328 #, fuzzy msgid "Capture device" msgstr "Felvevő hang eszköz:" -#: ../gtk/audio_assistant.c:327 +#: ../gtk/audio_assistant.c:329 #, fuzzy msgid "Recorded volume" msgstr "Felvételi forrás:" -#: ../gtk/audio_assistant.c:331 +#: ../gtk/audio_assistant.c:333 msgid "No voice" msgstr "" -#: ../gtk/audio_assistant.c:367 +#: ../gtk/audio_assistant.c:369 #, fuzzy msgid "Playback device" msgstr "Lejátszó hang eszköz:" -#: ../gtk/audio_assistant.c:368 +#: ../gtk/audio_assistant.c:370 msgid "Play three beeps" msgstr "" -#: ../gtk/audio_assistant.c:400 +#: ../gtk/audio_assistant.c:403 msgid "Press the record button and say some words" msgstr "" -#: ../gtk/audio_assistant.c:401 +#: ../gtk/audio_assistant.c:404 msgid "Listen to your record voice" msgstr "" -#: ../gtk/audio_assistant.c:430 +#: ../gtk/audio_assistant.c:433 msgid "Let's start Linphone now" msgstr "" -#: ../gtk/audio_assistant.c:488 +#: ../gtk/audio_assistant.c:496 #, fuzzy msgid "Audio Assistant" msgstr "Fiók varázsló" -#: ../gtk/audio_assistant.c:498 ../gtk/main.ui.h:31 +#: ../gtk/audio_assistant.c:506 ../gtk/main.ui.h:31 #, fuzzy msgid "Audio assistant" msgstr "Fiók varázsló" -#: ../gtk/audio_assistant.c:503 +#: ../gtk/audio_assistant.c:511 msgid "Mic Gain calibration" msgstr "" -#: ../gtk/audio_assistant.c:509 +#: ../gtk/audio_assistant.c:517 msgid "Speaker volume calibration" msgstr "" -#: ../gtk/audio_assistant.c:514 +#: ../gtk/audio_assistant.c:522 msgid "Record and Play" msgstr "" @@ -1806,96 +1810,65 @@ msgstr "Kapcsolódás..." msgid "Please wait while fetching configuration from server..." msgstr "" -#: ../coreapi/linphonecore.c:242 -msgid "aborted" -msgstr "megszakítva" - -#: ../coreapi/linphonecore.c:245 -msgid "completed" -msgstr "befejezve" - -#: ../coreapi/linphonecore.c:248 -msgid "missed" -msgstr "elhibázva" - -#: ../coreapi/linphonecore.c:253 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" -"%s nél %s\n" -"Tól: %s\n" -"Ig: %s\n" -"Állapot: %s\n" -"Időtartam: %i perc %i másodperc\n" - -#: ../coreapi/linphonecore.c:254 -msgid "Outgoing call" -msgstr "Kimenő hívás" - -#: ../coreapi/linphonecore.c:1287 +#: ../coreapi/linphonecore.c:1034 msgid "Ready" msgstr "Kész" -#: ../coreapi/linphonecore.c:2248 +#: ../coreapi/linphonecore.c:1967 #, fuzzy msgid "Configuring" msgstr "Információk" -#: ../coreapi/linphonecore.c:2410 +#: ../coreapi/linphonecore.c:2133 msgid "Looking for telephone number destination..." msgstr "Telefonszám-cél keresése..." -#: ../coreapi/linphonecore.c:2413 +#: ../coreapi/linphonecore.c:2136 msgid "Could not resolve this number." msgstr "Nem sikkerült értelmezni a számot." #. must be known at that time -#: ../coreapi/linphonecore.c:2695 +#: ../coreapi/linphonecore.c:2418 msgid "Contacting" msgstr "Kapcsolódás" -#: ../coreapi/linphonecore.c:2702 +#: ../coreapi/linphonecore.c:2425 msgid "Could not call" msgstr "Nem sikerült hívni" -#: ../coreapi/linphonecore.c:2852 +#: ../coreapi/linphonecore.c:2576 msgid "Sorry, we have reached the maximum number of simultaneous calls" msgstr "Elnézést, elértük a egyidejű hívások maximális számát" -#: ../coreapi/linphonecore.c:3022 +#: ../coreapi/linphonecore.c:2745 msgid "is contacting you" msgstr "kapcsolatba lépett veled." -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid " and asked autoanswer." msgstr "és automatikus választ kért." -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid "." msgstr "." -#: ../coreapi/linphonecore.c:3139 +#: ../coreapi/linphonecore.c:2865 msgid "Modifying call parameters..." msgstr "A hívási jellemzők módosítása..." -#: ../coreapi/linphonecore.c:3469 +#: ../coreapi/linphonecore.c:3194 msgid "Connected." msgstr "Kapcsolódva." -#: ../coreapi/linphonecore.c:3495 +#: ../coreapi/linphonecore.c:3220 msgid "Call aborted" msgstr "Hívás megszakítva" -#: ../coreapi/linphonecore.c:3685 +#: ../coreapi/linphonecore.c:3412 msgid "Could not pause the call" msgstr "Nem sikerült várakoztatni a hívást" -#: ../coreapi/linphonecore.c:3690 +#: ../coreapi/linphonecore.c:3417 msgid "Pausing the current call..." msgstr "Jelenlegi hívás várakoztatásának aktiválása..." @@ -1960,7 +1933,7 @@ msgstr "Időtartam" msgid "Unknown-bug" msgstr "Ismeretlen programhiba" -#: ../coreapi/proxy.c:279 +#: ../coreapi/proxy.c:314 msgid "" "The sip proxy address you entered is invalid, it must start with \"sip:\" " "followed by a hostname." @@ -1968,7 +1941,7 @@ msgstr "" "Az Ön által megadott SIP proxy cím érvénytelen. \"sip:\"-tal kell kezdődnie, " "ezt egy hosztnév követi." -#: ../coreapi/proxy.c:285 +#: ../coreapi/proxy.c:320 msgid "" "The sip identity you entered is invalid.\n" "It should look like sip:username@proxydomain, such as sip:alice@example.net" @@ -1977,130 +1950,155 @@ msgstr "" "Így kéne kinéznie: sip:felhasznalonev@proxytartomany, például sip:" "aladar@pelda.hu" -#: ../coreapi/proxy.c:1299 +#: ../coreapi/proxy.c:1369 #, c-format msgid "Could not login as %s" msgstr "Nem sikerült belépni ezzel: %s" -#: ../coreapi/callbacks.c:354 +#: ../coreapi/callbacks.c:355 msgid "Remote ringing." msgstr "Távoli csengés." -#: ../coreapi/callbacks.c:370 +#: ../coreapi/callbacks.c:373 msgid "Remote ringing..." msgstr "Távoli csengés..." -#: ../coreapi/callbacks.c:381 +#: ../coreapi/callbacks.c:384 msgid "Early media." msgstr "Korai médiák." -#: ../coreapi/callbacks.c:432 +#: ../coreapi/callbacks.c:435 #, c-format msgid "Call with %s is paused." msgstr "A hívás a következővel: %s várakoztatva" -#: ../coreapi/callbacks.c:445 +#: ../coreapi/callbacks.c:448 #, c-format msgid "Call answered by %s - on hold." msgstr "%s fogadta a hívást - várakoztatva." -#: ../coreapi/callbacks.c:456 +#: ../coreapi/callbacks.c:459 msgid "Call resumed." msgstr "Hívás visszatért" -#: ../coreapi/callbacks.c:461 +#: ../coreapi/callbacks.c:464 #, c-format msgid "Call answered by %s." msgstr "%s válaszolt a hívásra." -#: ../coreapi/callbacks.c:480 +#: ../coreapi/callbacks.c:483 msgid "Incompatible, check codecs or security settings..." msgstr "" "Nem kompatibilis, ellenőrizze a kódek- vagy a biztonsági beállításokat..." -#: ../coreapi/callbacks.c:531 +#: ../coreapi/callbacks.c:512 msgid "We have been resumed." msgstr "Visszatértünk." -#: ../coreapi/callbacks.c:541 +#: ../coreapi/callbacks.c:521 msgid "We are paused by other party." msgstr "Megállítva a másik fél által." -#: ../coreapi/callbacks.c:558 +#: ../coreapi/callbacks.c:556 msgid "Call is updated by remote." msgstr "A hívás távolról frissítve." -#: ../coreapi/callbacks.c:637 +#: ../coreapi/callbacks.c:658 msgid "Call terminated." msgstr "A hívás befejezve." -#: ../coreapi/callbacks.c:666 +#: ../coreapi/callbacks.c:687 msgid "User is busy." msgstr "A felhasználó foglalt." -#: ../coreapi/callbacks.c:667 +#: ../coreapi/callbacks.c:688 msgid "User is temporarily unavailable." msgstr "A felhasználó ideiglenesen nem elérhető" #. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:669 +#: ../coreapi/callbacks.c:690 msgid "User does not want to be disturbed." msgstr "A felhasználó nem akarja, hogy zavarják." -#: ../coreapi/callbacks.c:670 +#: ../coreapi/callbacks.c:691 msgid "Call declined." msgstr "Hívás elutasítva" -#: ../coreapi/callbacks.c:685 +#: ../coreapi/callbacks.c:706 msgid "Request timeout." msgstr "" -#: ../coreapi/callbacks.c:716 +#: ../coreapi/callbacks.c:737 msgid "Redirected" msgstr "Átirányítva" -#: ../coreapi/callbacks.c:766 +#: ../coreapi/callbacks.c:787 msgid "Incompatible media parameters." msgstr "Nem kompatibilis médiajellemzők." -#: ../coreapi/callbacks.c:777 +#: ../coreapi/callbacks.c:798 msgid "Call failed." msgstr "Nem sikerült a hívás." -#: ../coreapi/callbacks.c:852 +#: ../coreapi/callbacks.c:878 #, c-format msgid "Registration on %s successful." msgstr "A regisztáció a %s -n sikerült." -#: ../coreapi/callbacks.c:853 +#: ../coreapi/callbacks.c:879 #, c-format msgid "Unregistration on %s done." msgstr "A kiregisztrálás kész a következőn: %s ." -#: ../coreapi/callbacks.c:875 +#: ../coreapi/callbacks.c:897 msgid "no response timeout" msgstr "időtúllépés után nincs válasz" -#: ../coreapi/callbacks.c:878 +#: ../coreapi/callbacks.c:900 #, c-format msgid "Registration on %s failed: %s" msgstr "A regisztáció a %s -n nem sikerült: %s" -#: ../coreapi/callbacks.c:885 +#: ../coreapi/callbacks.c:907 msgid "Service unavailable, retrying" msgstr "" -#: ../coreapi/linphonecall.c:175 +#: ../coreapi/linphonecall.c:177 #, c-format msgid "Authentication token is %s" msgstr "Hitelesítési jel: %s" -#: ../coreapi/linphonecall.c:2994 +#: ../coreapi/linphonecall.c:2932 #, c-format msgid "You have missed %i call." msgid_plural "You have missed %i calls." msgstr[0] "Van %i nem fogadott hivás." +#~ msgid "aborted" +#~ msgstr "megszakítva" + +#~ msgid "completed" +#~ msgstr "befejezve" + +#~ msgid "missed" +#~ msgstr "elhibázva" + +#~ msgid "" +#~ "%s at %s\n" +#~ "From: %s\n" +#~ "To: %s\n" +#~ "Status: %s\n" +#~ "Duration: %i mn %i sec\n" +#~ msgstr "" +#~ "%s nél %s\n" +#~ "Tól: %s\n" +#~ "Ig: %s\n" +#~ "Állapot: %s\n" +#~ "Időtartam: %i perc %i másodperc\n" + +#~ msgid "Outgoing call" +#~ msgstr "Kimenő hívás" + #~ msgid "No response." #~ msgstr "Nincs válasz." diff --git a/po/it.po b/po/it.po index a04f95573..980db056b 100644 --- a/po/it.po +++ b/po/it.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: Linphone 3.2.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-01 21:24+0200\n" +"POT-Creation-Date: 2014-09-15 09:24+0200\n" "PO-Revision-Date: 2002-10-15 HO:MI+ZONE\n" "Last-Translator: Matteo Piazza \n" "Language-Team: it \n" @@ -15,12 +15,12 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:973 +#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:974 #, c-format msgid "Call %s" msgstr "Chiamata %s" -#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:974 +#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:975 #, c-format msgid "Send text to %s" msgstr "Invia testo a %s" @@ -30,52 +30,52 @@ msgstr "Invia testo a %s" msgid "Recent calls (%i)" msgstr "In chiamata con" -#: ../gtk/calllogs.c:312 +#: ../gtk/calllogs.c:314 msgid "n/a" msgstr "" -#: ../gtk/calllogs.c:315 +#: ../gtk/calllogs.c:317 #, fuzzy msgid "Aborted" msgstr "annullato" -#: ../gtk/calllogs.c:318 +#: ../gtk/calllogs.c:320 #, fuzzy msgid "Missed" msgstr "mancante" -#: ../gtk/calllogs.c:321 +#: ../gtk/calllogs.c:323 #, fuzzy msgid "Declined" msgstr "Rifiuta" -#: ../gtk/calllogs.c:327 +#: ../gtk/calllogs.c:329 #, c-format msgid "%i minute" msgid_plural "%i minutes" msgstr[0] "" msgstr[1] "" -#: ../gtk/calllogs.c:330 +#: ../gtk/calllogs.c:332 #, c-format msgid "%i second" msgid_plural "%i seconds" msgstr[0] "" msgstr[1] "" -#: ../gtk/calllogs.c:333 ../gtk/calllogs.c:339 +#: ../gtk/calllogs.c:335 ../gtk/calllogs.c:341 #, c-format msgid "%s\t%s" msgstr "" -#: ../gtk/calllogs.c:335 +#: ../gtk/calllogs.c:337 #, c-format msgid "" "%s\tQuality: %s\n" "%s\t%s\t" msgstr "" -#: ../gtk/calllogs.c:341 +#: ../gtk/calllogs.c:343 #, c-format msgid "" "%s\t\n" @@ -98,7 +98,7 @@ msgstr "" msgid "Couldn't find pixmap file: %s" msgstr "" -#: ../gtk/chat.c:363 ../gtk/friendlist.c:923 +#: ../gtk/chat.c:364 ../gtk/friendlist.c:924 msgid "Invalid sip contact !" msgstr "Contatto SIP non valido" @@ -147,7 +147,7 @@ msgstr "Configuratore di account" msgid "Call with %s" msgstr "Chat con %s" -#: ../gtk/main.c:1171 +#: ../gtk/main.c:1183 #, c-format msgid "" "%s would like to add you to his contact list.\n" @@ -159,74 +159,74 @@ msgstr "" "veda il tuo stato o aggiungerlo alla tua lista dei contatti Se rispondi no " "questo utente sarà momentaneamente bloccato." -#: ../gtk/main.c:1248 +#: ../gtk/main.c:1260 #, fuzzy, c-format msgid "" "Please enter your password for username %s\n" " at realm %s:" msgstr "Prego inserire la password per username %s e dominio %s" -#: ../gtk/main.c:1364 +#: ../gtk/main.c:1376 #, fuzzy msgid "Call error" msgstr "Cronologia" -#: ../gtk/main.c:1367 ../coreapi/linphonecore.c:3515 +#: ../gtk/main.c:1379 ../coreapi/linphonecore.c:3240 msgid "Call ended" msgstr "Chiamata terminata" -#: ../gtk/main.c:1370 ../coreapi/linphonecore.c:254 +#: ../gtk/main.c:1382 msgid "Incoming call" msgstr "Chimata in entrata" -#: ../gtk/main.c:1372 ../gtk/incall_view.c:513 ../gtk/main.ui.h:5 +#: ../gtk/main.c:1384 ../gtk/incall_view.c:522 ../gtk/main.ui.h:5 msgid "Answer" msgstr "" -#: ../gtk/main.c:1374 ../gtk/main.ui.h:6 +#: ../gtk/main.c:1386 ../gtk/main.ui.h:6 msgid "Decline" msgstr "Rifiuta" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy msgid "Call paused" msgstr "annullato" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy, c-format msgid "by %s" msgstr "Porte" -#: ../gtk/main.c:1447 +#: ../gtk/main.c:1459 #, c-format msgid "%s proposed to start video. Do you accept ?" msgstr "" -#: ../gtk/main.c:1609 +#: ../gtk/main.c:1621 msgid "Website link" msgstr "" -#: ../gtk/main.c:1658 +#: ../gtk/main.c:1670 msgid "Linphone - a video internet phone" msgstr "" -#: ../gtk/main.c:1750 +#: ../gtk/main.c:1762 #, c-format msgid "%s (Default)" msgstr "%s (Default)" -#: ../gtk/main.c:2086 ../coreapi/callbacks.c:927 +#: ../gtk/main.c:2099 ../coreapi/callbacks.c:949 #, c-format msgid "We are transferred to %s" msgstr "" -#: ../gtk/main.c:2096 +#: ../gtk/main.c:2109 msgid "" "No sound cards have been detected on this computer.\n" "You won't be able to send or receive audio calls." msgstr "" -#: ../gtk/main.c:2237 +#: ../gtk/main.c:2250 msgid "A free SIP video-phone" msgstr "" @@ -238,7 +238,7 @@ msgstr "" msgid "Presence status" msgstr "Presenza" -#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:550 ../gtk/contact.ui.h:1 +#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:552 ../gtk/contact.ui.h:1 msgid "Name" msgstr "Nome" @@ -256,141 +256,141 @@ msgstr "" msgid "Search in %s directory" msgstr "Cerca contatti nella directory %s" -#: ../gtk/friendlist.c:975 +#: ../gtk/friendlist.c:976 #, c-format msgid "Edit contact '%s'" msgstr "Modifica contatto %s" -#: ../gtk/friendlist.c:976 +#: ../gtk/friendlist.c:977 #, c-format msgid "Delete contact '%s'" msgstr "Elimina contatto %s" -#: ../gtk/friendlist.c:977 +#: ../gtk/friendlist.c:978 #, fuzzy, c-format msgid "Delete chat history of '%s'" msgstr "Elimina contatto %s" -#: ../gtk/friendlist.c:1028 +#: ../gtk/friendlist.c:1029 #, c-format msgid "Add new contact from %s directory" msgstr "Aggiungi nuovo contatto dalla directory %s" -#: ../gtk/propertybox.c:556 +#: ../gtk/propertybox.c:558 msgid "Rate (Hz)" msgstr "" -#: ../gtk/propertybox.c:562 +#: ../gtk/propertybox.c:564 msgid "Status" msgstr "Stato" -#: ../gtk/propertybox.c:568 +#: ../gtk/propertybox.c:570 #, fuzzy msgid "IP Bitrate (kbit/s)" msgstr "Bitrate Min (kbit/s)" -#: ../gtk/propertybox.c:575 +#: ../gtk/propertybox.c:577 msgid "Parameters" msgstr "Parametri" -#: ../gtk/propertybox.c:618 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:763 msgid "Enabled" msgstr "Attivato" -#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:622 ../gtk/propertybox.c:763 msgid "Disabled" msgstr "Disattivato" -#: ../gtk/propertybox.c:807 +#: ../gtk/propertybox.c:809 msgid "Account" msgstr "Account" -#: ../gtk/propertybox.c:1061 +#: ../gtk/propertybox.c:1063 msgid "English" msgstr "Inglese" -#: ../gtk/propertybox.c:1062 +#: ../gtk/propertybox.c:1064 msgid "French" msgstr "Francese" -#: ../gtk/propertybox.c:1063 +#: ../gtk/propertybox.c:1065 msgid "Swedish" msgstr "Svedese" -#: ../gtk/propertybox.c:1064 +#: ../gtk/propertybox.c:1066 msgid "Italian" msgstr "Italiano" -#: ../gtk/propertybox.c:1065 +#: ../gtk/propertybox.c:1067 msgid "Spanish" msgstr "Spagnolo" -#: ../gtk/propertybox.c:1066 +#: ../gtk/propertybox.c:1068 msgid "Brazilian Portugese" msgstr "" -#: ../gtk/propertybox.c:1067 +#: ../gtk/propertybox.c:1069 msgid "Polish" msgstr "Polacco" -#: ../gtk/propertybox.c:1068 +#: ../gtk/propertybox.c:1070 msgid "German" msgstr "Tedesco" -#: ../gtk/propertybox.c:1069 +#: ../gtk/propertybox.c:1071 msgid "Russian" msgstr "Russo" -#: ../gtk/propertybox.c:1070 +#: ../gtk/propertybox.c:1072 msgid "Japanese" msgstr "Giapponese" -#: ../gtk/propertybox.c:1071 +#: ../gtk/propertybox.c:1073 msgid "Dutch" msgstr "Olandese" -#: ../gtk/propertybox.c:1072 +#: ../gtk/propertybox.c:1074 msgid "Hungarian" msgstr "Ungherese" -#: ../gtk/propertybox.c:1073 +#: ../gtk/propertybox.c:1075 msgid "Czech" msgstr "Ceco" -#: ../gtk/propertybox.c:1074 +#: ../gtk/propertybox.c:1076 msgid "Chinese" msgstr "" -#: ../gtk/propertybox.c:1075 +#: ../gtk/propertybox.c:1077 msgid "Traditional Chinese" msgstr "" -#: ../gtk/propertybox.c:1076 +#: ../gtk/propertybox.c:1078 msgid "Norwegian" msgstr "" -#: ../gtk/propertybox.c:1077 +#: ../gtk/propertybox.c:1079 msgid "Hebrew" msgstr "" -#: ../gtk/propertybox.c:1078 +#: ../gtk/propertybox.c:1080 msgid "Serbian" msgstr "" -#: ../gtk/propertybox.c:1145 +#: ../gtk/propertybox.c:1147 msgid "" "You need to restart linphone for the new language selection to take effect." msgstr "Riavviare il software per utilizzare la nuova lingua selezionata" -#: ../gtk/propertybox.c:1223 +#: ../gtk/propertybox.c:1225 msgid "None" msgstr "" -#: ../gtk/propertybox.c:1227 +#: ../gtk/propertybox.c:1229 msgid "SRTP" msgstr "" -#: ../gtk/propertybox.c:1233 +#: ../gtk/propertybox.c:1235 msgid "ZRTP" msgstr "" @@ -465,110 +465,114 @@ msgstr "" msgid "Enter your linphone.org username" msgstr "" -#: ../gtk/setupwizard.c:96 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 +#: ../gtk/setupwizard.c:102 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 msgid "Username:" msgstr "Manuale utente" -#: ../gtk/setupwizard.c:98 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 +#: ../gtk/setupwizard.c:104 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 msgid "Password:" msgstr "Password:" -#: ../gtk/setupwizard.c:118 +#: ../gtk/setupwizard.c:124 msgid "Enter your account informations" msgstr "" -#: ../gtk/setupwizard.c:125 +#: ../gtk/setupwizard.c:140 #, fuzzy msgid "Username*" msgstr "Username" -#: ../gtk/setupwizard.c:126 +#: ../gtk/setupwizard.c:141 #, fuzzy msgid "Password*" msgstr "Password" -#: ../gtk/setupwizard.c:129 +#: ../gtk/setupwizard.c:144 msgid "Domain*" msgstr "" -#: ../gtk/setupwizard.c:130 +#: ../gtk/setupwizard.c:145 msgid "Proxy" msgstr "" -#: ../gtk/setupwizard.c:302 +#: ../gtk/setupwizard.c:317 msgid "(*) Required fields" msgstr "" -#: ../gtk/setupwizard.c:303 +#: ../gtk/setupwizard.c:318 #, fuzzy msgid "Username: (*)" msgstr "Manuale utente" -#: ../gtk/setupwizard.c:305 +#: ../gtk/setupwizard.c:320 #, fuzzy msgid "Password: (*)" msgstr "Password:" -#: ../gtk/setupwizard.c:307 +#: ../gtk/setupwizard.c:322 msgid "Email: (*)" msgstr "" -#: ../gtk/setupwizard.c:309 +#: ../gtk/setupwizard.c:324 msgid "Confirm your password: (*)" msgstr "" -#: ../gtk/setupwizard.c:373 +#: ../gtk/setupwizard.c:338 +msgid "Keep me informed with linphone updates" +msgstr "" + +#: ../gtk/setupwizard.c:394 msgid "" "Error, account not validated, username already used or server unreachable.\n" "Please go back and try again." msgstr "" -#: ../gtk/setupwizard.c:384 +#: ../gtk/setupwizard.c:405 msgid "Thank you. Your account is now configured and ready for use." msgstr "Grazie. Il tuo account è configurato e pronto all'uso" -#: ../gtk/setupwizard.c:392 +#: ../gtk/setupwizard.c:413 msgid "" "Please validate your account by clicking on the link we just sent you by " "email.\n" "Then come back here and press Next button." msgstr "" -#: ../gtk/setupwizard.c:564 +#: ../gtk/setupwizard.c:600 #, fuzzy msgid "SIP account configuration assistant" msgstr "Configuratore di account" -#: ../gtk/setupwizard.c:582 +#: ../gtk/setupwizard.c:618 msgid "Welcome to the account setup assistant" msgstr "Benvenuto nel configuratore di account" -#: ../gtk/setupwizard.c:587 +#: ../gtk/setupwizard.c:623 msgid "Account setup assistant" msgstr "Configuratore di account" -#: ../gtk/setupwizard.c:593 +#: ../gtk/setupwizard.c:629 #, fuzzy msgid "Configure your account (step 1/1)" msgstr "Configurazione SIP account" -#: ../gtk/setupwizard.c:598 +#: ../gtk/setupwizard.c:634 msgid "Enter your sip username (step 1/1)" msgstr "" -#: ../gtk/setupwizard.c:602 +#: ../gtk/setupwizard.c:638 msgid "Enter account information (step 1/2)" msgstr "" -#: ../gtk/setupwizard.c:611 +#: ../gtk/setupwizard.c:647 msgid "Validation (step 2/2)" msgstr "" -#: ../gtk/setupwizard.c:616 +#: ../gtk/setupwizard.c:652 msgid "Error" msgstr "" -#: ../gtk/setupwizard.c:620 ../gtk/audio_assistant.c:519 +#: ../gtk/setupwizard.c:656 ../gtk/audio_assistant.c:527 #, fuzzy msgid "Terminating" msgstr "Termina chiamata" @@ -639,134 +643,134 @@ msgstr "Filtro ICE" msgid "Direct or through server" msgstr "" -#: ../gtk/incall_view.c:266 ../gtk/incall_view.c:276 +#: ../gtk/incall_view.c:267 ../gtk/incall_view.c:279 #, c-format msgid "" "download: %f\n" "upload: %f (kbit/s)" msgstr "" -#: ../gtk/incall_view.c:271 ../gtk/incall_view.c:272 +#: ../gtk/incall_view.c:272 ../gtk/incall_view.c:274 #, c-format -msgid "%ix%i" +msgid "%ix%i @ %f fps" msgstr "" -#: ../gtk/incall_view.c:301 +#: ../gtk/incall_view.c:304 #, c-format msgid "%.3f seconds" msgstr "" -#: ../gtk/incall_view.c:399 ../gtk/main.ui.h:12 +#: ../gtk/incall_view.c:407 ../gtk/main.ui.h:12 msgid "Hang up" msgstr "" -#: ../gtk/incall_view.c:492 +#: ../gtk/incall_view.c:501 #, fuzzy msgid "Calling..." msgstr "Linguaggio" -#: ../gtk/incall_view.c:495 ../gtk/incall_view.c:698 +#: ../gtk/incall_view.c:504 ../gtk/incall_view.c:707 msgid "00::00::00" msgstr "" -#: ../gtk/incall_view.c:506 +#: ../gtk/incall_view.c:515 #, fuzzy msgid "Incoming call" msgstr "Chimata in entrata" -#: ../gtk/incall_view.c:543 +#: ../gtk/incall_view.c:552 msgid "good" msgstr "" -#: ../gtk/incall_view.c:545 +#: ../gtk/incall_view.c:554 msgid "average" msgstr "" -#: ../gtk/incall_view.c:547 +#: ../gtk/incall_view.c:556 msgid "poor" msgstr "" -#: ../gtk/incall_view.c:549 +#: ../gtk/incall_view.c:558 msgid "very poor" msgstr "" -#: ../gtk/incall_view.c:551 +#: ../gtk/incall_view.c:560 msgid "too bad" msgstr "" -#: ../gtk/incall_view.c:552 ../gtk/incall_view.c:568 +#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:577 msgid "unavailable" msgstr "" -#: ../gtk/incall_view.c:660 +#: ../gtk/incall_view.c:669 msgid "Secured by SRTP" msgstr "" -#: ../gtk/incall_view.c:666 +#: ../gtk/incall_view.c:675 #, c-format msgid "Secured by ZRTP - [auth token: %s]" msgstr "" -#: ../gtk/incall_view.c:672 +#: ../gtk/incall_view.c:681 msgid "Set unverified" msgstr "" -#: ../gtk/incall_view.c:672 ../gtk/main.ui.h:4 +#: ../gtk/incall_view.c:681 ../gtk/main.ui.h:4 msgid "Set verified" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In conference" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 #, fuzzy msgid "In call" msgstr "In chiamata con" -#: ../gtk/incall_view.c:729 +#: ../gtk/incall_view.c:738 #, fuzzy msgid "Paused call" msgstr "Termina chiamata" -#: ../gtk/incall_view.c:742 +#: ../gtk/incall_view.c:751 #, c-format msgid "%02i::%02i::%02i" msgstr "" -#: ../gtk/incall_view.c:760 +#: ../gtk/incall_view.c:772 msgid "Call ended." msgstr "Chiamata terminata." -#: ../gtk/incall_view.c:791 +#: ../gtk/incall_view.c:803 msgid "Transfer in progress" msgstr "" -#: ../gtk/incall_view.c:794 +#: ../gtk/incall_view.c:806 msgid "Transfer done." msgstr "" -#: ../gtk/incall_view.c:797 +#: ../gtk/incall_view.c:809 #, fuzzy msgid "Transfer failed." msgstr "Chiamata rifiutata" -#: ../gtk/incall_view.c:841 +#: ../gtk/incall_view.c:853 msgid "Resume" msgstr "" -#: ../gtk/incall_view.c:848 ../gtk/main.ui.h:9 +#: ../gtk/incall_view.c:860 ../gtk/main.ui.h:9 msgid "Pause" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, c-format msgid "" "Recording into\n" "%s %s" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 msgid "(Paused)" msgstr "" @@ -801,7 +805,7 @@ msgstr "" msgid "Too loud" msgstr "" -#: ../gtk/audio_assistant.c:316 +#: ../gtk/audio_assistant.c:318 #, fuzzy msgid "" "Welcome !\n" @@ -810,59 +814,59 @@ msgstr "" "Benvenuti !\n" "La procedura vi aiutera a configurare un account SIP." -#: ../gtk/audio_assistant.c:326 +#: ../gtk/audio_assistant.c:328 #, fuzzy msgid "Capture device" msgstr "Dispositivo microfono:" -#: ../gtk/audio_assistant.c:327 +#: ../gtk/audio_assistant.c:329 msgid "Recorded volume" msgstr "" -#: ../gtk/audio_assistant.c:331 +#: ../gtk/audio_assistant.c:333 msgid "No voice" msgstr "" -#: ../gtk/audio_assistant.c:367 +#: ../gtk/audio_assistant.c:369 #, fuzzy msgid "Playback device" msgstr "Dispositivo uscita audio:" -#: ../gtk/audio_assistant.c:368 +#: ../gtk/audio_assistant.c:370 msgid "Play three beeps" msgstr "" -#: ../gtk/audio_assistant.c:400 +#: ../gtk/audio_assistant.c:403 msgid "Press the record button and say some words" msgstr "" -#: ../gtk/audio_assistant.c:401 +#: ../gtk/audio_assistant.c:404 msgid "Listen to your record voice" msgstr "" -#: ../gtk/audio_assistant.c:430 +#: ../gtk/audio_assistant.c:433 msgid "Let's start Linphone now" msgstr "" -#: ../gtk/audio_assistant.c:488 +#: ../gtk/audio_assistant.c:496 #, fuzzy msgid "Audio Assistant" msgstr "Configuratore" -#: ../gtk/audio_assistant.c:498 ../gtk/main.ui.h:31 +#: ../gtk/audio_assistant.c:506 ../gtk/main.ui.h:31 #, fuzzy msgid "Audio assistant" msgstr "Configuratore di account" -#: ../gtk/audio_assistant.c:503 +#: ../gtk/audio_assistant.c:511 msgid "Mic Gain calibration" msgstr "" -#: ../gtk/audio_assistant.c:509 +#: ../gtk/audio_assistant.c:517 msgid "Speaker volume calibration" msgstr "" -#: ../gtk/audio_assistant.c:514 +#: ../gtk/audio_assistant.c:522 msgid "Record and Play" msgstr "" @@ -1830,100 +1834,69 @@ msgstr "In connessione..." msgid "Please wait while fetching configuration from server..." msgstr "" -#: ../coreapi/linphonecore.c:242 -msgid "aborted" -msgstr "annullato" - -#: ../coreapi/linphonecore.c:245 -msgid "completed" -msgstr "comletato" - -#: ../coreapi/linphonecore.c:248 -msgid "missed" -msgstr "mancante" - -#: ../coreapi/linphonecore.c:253 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" -"%s at %s\n" -"Da: %s\n" -"Verso: %s\n" -"Stato: %s\n" -"Durata: %i mn %i sec\n" - -#: ../coreapi/linphonecore.c:254 -msgid "Outgoing call" -msgstr "Chiamata in uscita" - -#: ../coreapi/linphonecore.c:1287 +#: ../coreapi/linphonecore.c:1034 msgid "Ready" msgstr "Pronto" -#: ../coreapi/linphonecore.c:2248 +#: ../coreapi/linphonecore.c:1967 #, fuzzy msgid "Configuring" msgstr "Informazioni" -#: ../coreapi/linphonecore.c:2410 +#: ../coreapi/linphonecore.c:2133 msgid "Looking for telephone number destination..." msgstr "Ricerca numero destinazione..." -#: ../coreapi/linphonecore.c:2413 +#: ../coreapi/linphonecore.c:2136 msgid "Could not resolve this number." msgstr "Impossibile risolvere il numero." #. must be known at that time -#: ../coreapi/linphonecore.c:2695 +#: ../coreapi/linphonecore.c:2418 msgid "Contacting" msgstr "In connessione" -#: ../coreapi/linphonecore.c:2702 +#: ../coreapi/linphonecore.c:2425 #, fuzzy msgid "Could not call" msgstr "chiamata fallita" -#: ../coreapi/linphonecore.c:2852 +#: ../coreapi/linphonecore.c:2576 msgid "Sorry, we have reached the maximum number of simultaneous calls" msgstr "" -#: ../coreapi/linphonecore.c:3022 +#: ../coreapi/linphonecore.c:2745 #, fuzzy msgid "is contacting you" msgstr "ti sta conttatando." -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid " and asked autoanswer." msgstr "" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid "." msgstr "" -#: ../coreapi/linphonecore.c:3139 +#: ../coreapi/linphonecore.c:2865 msgid "Modifying call parameters..." msgstr "" -#: ../coreapi/linphonecore.c:3469 +#: ../coreapi/linphonecore.c:3194 msgid "Connected." msgstr "Connessione" -#: ../coreapi/linphonecore.c:3495 +#: ../coreapi/linphonecore.c:3220 #, fuzzy msgid "Call aborted" msgstr "annullato" -#: ../coreapi/linphonecore.c:3685 +#: ../coreapi/linphonecore.c:3412 #, fuzzy msgid "Could not pause the call" msgstr "chiamata fallita" -#: ../coreapi/linphonecore.c:3690 +#: ../coreapi/linphonecore.c:3417 #, fuzzy msgid "Pausing the current call..." msgstr "Mostra chiamata corrente" @@ -1989,7 +1962,7 @@ msgstr "Durata" msgid "Unknown-bug" msgstr "Bug-sconosciuto" -#: ../coreapi/proxy.c:279 +#: ../coreapi/proxy.c:314 msgid "" "The sip proxy address you entered is invalid, it must start with \"sip:\" " "followed by a hostname." @@ -1997,7 +1970,7 @@ msgstr "" "L'indirizzo sip proxy utilizzato è invalido, deve iniziare con \"sip:\" " "seguito dall' hostaname." -#: ../coreapi/proxy.c:285 +#: ../coreapi/proxy.c:320 msgid "" "The sip identity you entered is invalid.\n" "It should look like sip:username@proxydomain, such as sip:alice@example.net" @@ -2005,133 +1978,158 @@ msgstr "" "L'identità sip utilizza è invalida.\n" "Dovrebbre essere sip:username@proxydomain, esempio: sip:alice@example.net" -#: ../coreapi/proxy.c:1299 +#: ../coreapi/proxy.c:1369 #, c-format msgid "Could not login as %s" msgstr "impossibile login come %s" -#: ../coreapi/callbacks.c:354 +#: ../coreapi/callbacks.c:355 msgid "Remote ringing." msgstr "" -#: ../coreapi/callbacks.c:370 +#: ../coreapi/callbacks.c:373 msgid "Remote ringing..." msgstr "" -#: ../coreapi/callbacks.c:381 +#: ../coreapi/callbacks.c:384 msgid "Early media." msgstr "" -#: ../coreapi/callbacks.c:432 +#: ../coreapi/callbacks.c:435 #, fuzzy, c-format msgid "Call with %s is paused." msgstr "Chat con %s" -#: ../coreapi/callbacks.c:445 +#: ../coreapi/callbacks.c:448 #, c-format msgid "Call answered by %s - on hold." msgstr "" -#: ../coreapi/callbacks.c:456 +#: ../coreapi/callbacks.c:459 #, fuzzy msgid "Call resumed." msgstr "Chiamata terminata" -#: ../coreapi/callbacks.c:461 +#: ../coreapi/callbacks.c:464 #, c-format msgid "Call answered by %s." msgstr "" -#: ../coreapi/callbacks.c:480 +#: ../coreapi/callbacks.c:483 msgid "Incompatible, check codecs or security settings..." msgstr "" -#: ../coreapi/callbacks.c:531 +#: ../coreapi/callbacks.c:512 msgid "We have been resumed." msgstr "" -#: ../coreapi/callbacks.c:541 +#: ../coreapi/callbacks.c:521 msgid "We are paused by other party." msgstr "" -#: ../coreapi/callbacks.c:558 +#: ../coreapi/callbacks.c:556 msgid "Call is updated by remote." msgstr "" -#: ../coreapi/callbacks.c:637 +#: ../coreapi/callbacks.c:658 msgid "Call terminated." msgstr "Chiamata terminata." -#: ../coreapi/callbacks.c:666 +#: ../coreapi/callbacks.c:687 msgid "User is busy." msgstr "Utente occupato" -#: ../coreapi/callbacks.c:667 +#: ../coreapi/callbacks.c:688 msgid "User is temporarily unavailable." msgstr "Utente non disponibile" #. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:669 +#: ../coreapi/callbacks.c:690 msgid "User does not want to be disturbed." msgstr "L'utente non vuole essere disturbato" -#: ../coreapi/callbacks.c:670 +#: ../coreapi/callbacks.c:691 msgid "Call declined." msgstr "Chiamata rifiutata" -#: ../coreapi/callbacks.c:685 +#: ../coreapi/callbacks.c:706 msgid "Request timeout." msgstr "" -#: ../coreapi/callbacks.c:716 +#: ../coreapi/callbacks.c:737 #, fuzzy msgid "Redirected" msgstr "Rediretto verso %s..." -#: ../coreapi/callbacks.c:766 +#: ../coreapi/callbacks.c:787 msgid "Incompatible media parameters." msgstr "" -#: ../coreapi/callbacks.c:777 +#: ../coreapi/callbacks.c:798 #, fuzzy msgid "Call failed." msgstr "Chiamata rifiutata" -#: ../coreapi/callbacks.c:852 +#: ../coreapi/callbacks.c:878 #, c-format msgid "Registration on %s successful." msgstr "Registrazione su %s attiva" -#: ../coreapi/callbacks.c:853 +#: ../coreapi/callbacks.c:879 #, c-format msgid "Unregistration on %s done." msgstr "Unregistrazione su %s" -#: ../coreapi/callbacks.c:875 +#: ../coreapi/callbacks.c:897 msgid "no response timeout" msgstr "timeout no risposta" -#: ../coreapi/callbacks.c:878 +#: ../coreapi/callbacks.c:900 #, c-format msgid "Registration on %s failed: %s" msgstr "Registrazione su %s fallita: %s" -#: ../coreapi/callbacks.c:885 +#: ../coreapi/callbacks.c:907 msgid "Service unavailable, retrying" msgstr "" -#: ../coreapi/linphonecall.c:175 +#: ../coreapi/linphonecall.c:177 #, fuzzy, c-format msgid "Authentication token is %s" msgstr "Linphone - Autenticazione richiesta" -#: ../coreapi/linphonecall.c:2994 +#: ../coreapi/linphonecall.c:2932 #, c-format msgid "You have missed %i call." msgid_plural "You have missed %i calls." msgstr[0] "" msgstr[1] "" +#~ msgid "aborted" +#~ msgstr "annullato" + +#~ msgid "completed" +#~ msgstr "comletato" + +#~ msgid "missed" +#~ msgstr "mancante" + +#~ msgid "" +#~ "%s at %s\n" +#~ "From: %s\n" +#~ "To: %s\n" +#~ "Status: %s\n" +#~ "Duration: %i mn %i sec\n" +#~ msgstr "" +#~ "%s at %s\n" +#~ "Da: %s\n" +#~ "Verso: %s\n" +#~ "Stato: %s\n" +#~ "Durata: %i mn %i sec\n" + +#~ msgid "Outgoing call" +#~ msgstr "Chiamata in uscita" + #, fuzzy #~ msgid "No response." #~ msgstr "timeout no risposta" diff --git a/po/ja.po b/po/ja.po index 3cb7d0a36..6a5e37625 100644 --- a/po/ja.po +++ b/po/ja.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: linphone 0.10\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-01 21:24+0200\n" +"POT-Creation-Date: 2014-09-15 09:24+0200\n" "PO-Revision-Date: 2003-01-21 00:05+9000\n" "Last-Translator: YAMAGUCHI YOSHIYA \n" "Language-Team: \n" @@ -17,12 +17,12 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:973 +#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:974 #, c-format msgid "Call %s" msgstr "" -#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:974 +#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:975 #, c-format msgid "Send text to %s" msgstr "" @@ -32,51 +32,51 @@ msgstr "" msgid "Recent calls (%i)" msgstr "接続中" -#: ../gtk/calllogs.c:312 +#: ../gtk/calllogs.c:314 msgid "n/a" msgstr "" -#: ../gtk/calllogs.c:315 +#: ../gtk/calllogs.c:317 #, fuzzy msgid "Aborted" msgstr "通話はキャンセルされました。" -#: ../gtk/calllogs.c:318 +#: ../gtk/calllogs.c:320 msgid "Missed" msgstr "" -#: ../gtk/calllogs.c:321 +#: ../gtk/calllogs.c:323 #, fuzzy msgid "Declined" msgstr "ライン入力" -#: ../gtk/calllogs.c:327 +#: ../gtk/calllogs.c:329 #, c-format msgid "%i minute" msgid_plural "%i minutes" msgstr[0] "" msgstr[1] "" -#: ../gtk/calllogs.c:330 +#: ../gtk/calllogs.c:332 #, c-format msgid "%i second" msgid_plural "%i seconds" msgstr[0] "" msgstr[1] "" -#: ../gtk/calllogs.c:333 ../gtk/calllogs.c:339 +#: ../gtk/calllogs.c:335 ../gtk/calllogs.c:341 #, c-format msgid "%s\t%s" msgstr "" -#: ../gtk/calllogs.c:335 +#: ../gtk/calllogs.c:337 #, c-format msgid "" "%s\tQuality: %s\n" "%s\t%s\t" msgstr "" -#: ../gtk/calllogs.c:341 +#: ../gtk/calllogs.c:343 #, c-format msgid "" "%s\t\n" @@ -96,7 +96,7 @@ msgstr "" msgid "Couldn't find pixmap file: %s" msgstr "pixmapファイルが見つかりません %s" -#: ../gtk/chat.c:363 ../gtk/friendlist.c:923 +#: ../gtk/chat.c:364 ../gtk/friendlist.c:924 msgid "Invalid sip contact !" msgstr "" @@ -144,7 +144,7 @@ msgstr "" msgid "Call with %s" msgstr "" -#: ../gtk/main.c:1171 +#: ../gtk/main.c:1183 #, c-format msgid "" "%s would like to add you to his contact list.\n" @@ -153,76 +153,76 @@ msgid "" "If you answer no, this person will be temporarily blacklisted." msgstr "" -#: ../gtk/main.c:1248 +#: ../gtk/main.c:1260 #, c-format msgid "" "Please enter your password for username %s\n" " at realm %s:" msgstr "" -#: ../gtk/main.c:1364 +#: ../gtk/main.c:1376 #, fuzzy msgid "Call error" msgstr "通話はキャンセルされました。" -#: ../gtk/main.c:1367 ../coreapi/linphonecore.c:3515 +#: ../gtk/main.c:1379 ../coreapi/linphonecore.c:3240 #, fuzzy msgid "Call ended" msgstr "通話は拒否されました。" -#: ../gtk/main.c:1370 ../coreapi/linphonecore.c:254 +#: ../gtk/main.c:1382 msgid "Incoming call" msgstr "" -#: ../gtk/main.c:1372 ../gtk/incall_view.c:513 ../gtk/main.ui.h:5 +#: ../gtk/main.c:1384 ../gtk/incall_view.c:522 ../gtk/main.ui.h:5 msgid "Answer" msgstr "" -#: ../gtk/main.c:1374 ../gtk/main.ui.h:6 +#: ../gtk/main.c:1386 ../gtk/main.ui.h:6 #, fuzzy msgid "Decline" msgstr "ライン入力" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy msgid "Call paused" msgstr "通話はキャンセルされました。" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy, c-format msgid "by %s" msgstr "接続中" -#: ../gtk/main.c:1447 +#: ../gtk/main.c:1459 #, c-format msgid "%s proposed to start video. Do you accept ?" msgstr "" -#: ../gtk/main.c:1609 +#: ../gtk/main.c:1621 msgid "Website link" msgstr "" -#: ../gtk/main.c:1658 +#: ../gtk/main.c:1670 msgid "Linphone - a video internet phone" msgstr "" -#: ../gtk/main.c:1750 +#: ../gtk/main.c:1762 #, c-format msgid "%s (Default)" msgstr "" -#: ../gtk/main.c:2086 ../coreapi/callbacks.c:927 +#: ../gtk/main.c:2099 ../coreapi/callbacks.c:949 #, c-format msgid "We are transferred to %s" msgstr "" -#: ../gtk/main.c:2096 +#: ../gtk/main.c:2109 msgid "" "No sound cards have been detected on this computer.\n" "You won't be able to send or receive audio calls." msgstr "" -#: ../gtk/main.c:2237 +#: ../gtk/main.c:2250 msgid "A free SIP video-phone" msgstr "" @@ -236,7 +236,7 @@ msgstr "電話帳" msgid "Presence status" msgstr "状態" -#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:550 ../gtk/contact.ui.h:1 +#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:552 ../gtk/contact.ui.h:1 msgid "Name" msgstr "名前" @@ -254,142 +254,142 @@ msgstr "" msgid "Search in %s directory" msgstr "" -#: ../gtk/friendlist.c:975 +#: ../gtk/friendlist.c:976 #, fuzzy, c-format msgid "Edit contact '%s'" msgstr "(接続するための情報がありません!)" -#: ../gtk/friendlist.c:976 +#: ../gtk/friendlist.c:977 #, c-format msgid "Delete contact '%s'" msgstr "" -#: ../gtk/friendlist.c:977 +#: ../gtk/friendlist.c:978 #, c-format msgid "Delete chat history of '%s'" msgstr "" -#: ../gtk/friendlist.c:1028 +#: ../gtk/friendlist.c:1029 #, c-format msgid "Add new contact from %s directory" msgstr "" -#: ../gtk/propertybox.c:556 +#: ../gtk/propertybox.c:558 msgid "Rate (Hz)" msgstr "" -#: ../gtk/propertybox.c:562 +#: ../gtk/propertybox.c:564 msgid "Status" msgstr "状態" -#: ../gtk/propertybox.c:568 +#: ../gtk/propertybox.c:570 #, fuzzy msgid "IP Bitrate (kbit/s)" msgstr "最低限のビットレート (kbit/s)" -#: ../gtk/propertybox.c:575 +#: ../gtk/propertybox.c:577 msgid "Parameters" msgstr "パラメーター" -#: ../gtk/propertybox.c:618 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:763 msgid "Enabled" msgstr "使用する" -#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:622 ../gtk/propertybox.c:763 msgid "Disabled" msgstr "使用しない" -#: ../gtk/propertybox.c:807 +#: ../gtk/propertybox.c:809 msgid "Account" msgstr "" -#: ../gtk/propertybox.c:1061 +#: ../gtk/propertybox.c:1063 msgid "English" msgstr "" -#: ../gtk/propertybox.c:1062 +#: ../gtk/propertybox.c:1064 msgid "French" msgstr "Français" -#: ../gtk/propertybox.c:1063 +#: ../gtk/propertybox.c:1065 msgid "Swedish" msgstr "" -#: ../gtk/propertybox.c:1064 +#: ../gtk/propertybox.c:1066 msgid "Italian" msgstr "" -#: ../gtk/propertybox.c:1065 +#: ../gtk/propertybox.c:1067 msgid "Spanish" msgstr "" -#: ../gtk/propertybox.c:1066 +#: ../gtk/propertybox.c:1068 msgid "Brazilian Portugese" msgstr "" -#: ../gtk/propertybox.c:1067 +#: ../gtk/propertybox.c:1069 msgid "Polish" msgstr "" -#: ../gtk/propertybox.c:1068 +#: ../gtk/propertybox.c:1070 msgid "German" msgstr "" -#: ../gtk/propertybox.c:1069 +#: ../gtk/propertybox.c:1071 msgid "Russian" msgstr "" -#: ../gtk/propertybox.c:1070 +#: ../gtk/propertybox.c:1072 msgid "Japanese" msgstr "日本語" -#: ../gtk/propertybox.c:1071 +#: ../gtk/propertybox.c:1073 msgid "Dutch" msgstr "" -#: ../gtk/propertybox.c:1072 +#: ../gtk/propertybox.c:1074 msgid "Hungarian" msgstr "Magyar" -#: ../gtk/propertybox.c:1073 +#: ../gtk/propertybox.c:1075 msgid "Czech" msgstr "čeština" -#: ../gtk/propertybox.c:1074 +#: ../gtk/propertybox.c:1076 msgid "Chinese" msgstr "简体中文" -#: ../gtk/propertybox.c:1075 +#: ../gtk/propertybox.c:1077 msgid "Traditional Chinese" msgstr "" -#: ../gtk/propertybox.c:1076 +#: ../gtk/propertybox.c:1078 msgid "Norwegian" msgstr "" -#: ../gtk/propertybox.c:1077 +#: ../gtk/propertybox.c:1079 msgid "Hebrew" msgstr "" -#: ../gtk/propertybox.c:1078 +#: ../gtk/propertybox.c:1080 msgid "Serbian" msgstr "" -#: ../gtk/propertybox.c:1145 +#: ../gtk/propertybox.c:1147 msgid "" "You need to restart linphone for the new language selection to take effect." msgstr "" -#: ../gtk/propertybox.c:1223 +#: ../gtk/propertybox.c:1225 #, fuzzy msgid "None" msgstr "ありません。" -#: ../gtk/propertybox.c:1227 +#: ../gtk/propertybox.c:1229 msgid "SRTP" msgstr "" -#: ../gtk/propertybox.c:1233 +#: ../gtk/propertybox.c:1235 msgid "ZRTP" msgstr "" @@ -459,110 +459,114 @@ msgstr "" msgid "Enter your linphone.org username" msgstr "" -#: ../gtk/setupwizard.c:96 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 +#: ../gtk/setupwizard.c:102 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 #, fuzzy msgid "Username:" msgstr "ユーザーマニュアル" -#: ../gtk/setupwizard.c:98 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 +#: ../gtk/setupwizard.c:104 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 #, fuzzy msgid "Password:" msgstr "パスワード" -#: ../gtk/setupwizard.c:118 +#: ../gtk/setupwizard.c:124 msgid "Enter your account informations" msgstr "" -#: ../gtk/setupwizard.c:125 +#: ../gtk/setupwizard.c:140 #, fuzzy msgid "Username*" msgstr "ユーザーマニュアル" -#: ../gtk/setupwizard.c:126 +#: ../gtk/setupwizard.c:141 #, fuzzy msgid "Password*" msgstr "パスワード" -#: ../gtk/setupwizard.c:129 +#: ../gtk/setupwizard.c:144 msgid "Domain*" msgstr "" -#: ../gtk/setupwizard.c:130 +#: ../gtk/setupwizard.c:145 msgid "Proxy" msgstr "" -#: ../gtk/setupwizard.c:302 +#: ../gtk/setupwizard.c:317 msgid "(*) Required fields" msgstr "" -#: ../gtk/setupwizard.c:303 +#: ../gtk/setupwizard.c:318 #, fuzzy msgid "Username: (*)" msgstr "ユーザーマニュアル" -#: ../gtk/setupwizard.c:305 +#: ../gtk/setupwizard.c:320 #, fuzzy msgid "Password: (*)" msgstr "パスワード" -#: ../gtk/setupwizard.c:307 +#: ../gtk/setupwizard.c:322 msgid "Email: (*)" msgstr "" -#: ../gtk/setupwizard.c:309 +#: ../gtk/setupwizard.c:324 msgid "Confirm your password: (*)" msgstr "" -#: ../gtk/setupwizard.c:373 +#: ../gtk/setupwizard.c:338 +msgid "Keep me informed with linphone updates" +msgstr "" + +#: ../gtk/setupwizard.c:394 msgid "" "Error, account not validated, username already used or server unreachable.\n" "Please go back and try again." msgstr "" -#: ../gtk/setupwizard.c:384 +#: ../gtk/setupwizard.c:405 msgid "Thank you. Your account is now configured and ready for use." msgstr "" -#: ../gtk/setupwizard.c:392 +#: ../gtk/setupwizard.c:413 msgid "" "Please validate your account by clicking on the link we just sent you by " "email.\n" "Then come back here and press Next button." msgstr "" -#: ../gtk/setupwizard.c:564 +#: ../gtk/setupwizard.c:600 msgid "SIP account configuration assistant" msgstr "" -#: ../gtk/setupwizard.c:582 +#: ../gtk/setupwizard.c:618 msgid "Welcome to the account setup assistant" msgstr "" -#: ../gtk/setupwizard.c:587 +#: ../gtk/setupwizard.c:623 msgid "Account setup assistant" msgstr "" -#: ../gtk/setupwizard.c:593 +#: ../gtk/setupwizard.c:629 msgid "Configure your account (step 1/1)" msgstr "" -#: ../gtk/setupwizard.c:598 +#: ../gtk/setupwizard.c:634 msgid "Enter your sip username (step 1/1)" msgstr "" -#: ../gtk/setupwizard.c:602 +#: ../gtk/setupwizard.c:638 msgid "Enter account information (step 1/2)" msgstr "" -#: ../gtk/setupwizard.c:611 +#: ../gtk/setupwizard.c:647 msgid "Validation (step 2/2)" msgstr "" -#: ../gtk/setupwizard.c:616 +#: ../gtk/setupwizard.c:652 msgid "Error" msgstr "" -#: ../gtk/setupwizard.c:620 ../gtk/audio_assistant.c:519 +#: ../gtk/setupwizard.c:656 ../gtk/audio_assistant.c:527 msgid "Terminating" msgstr "" @@ -631,135 +635,135 @@ msgstr "通話はキャンセルされました。" msgid "Direct or through server" msgstr "" -#: ../gtk/incall_view.c:266 ../gtk/incall_view.c:276 +#: ../gtk/incall_view.c:267 ../gtk/incall_view.c:279 #, c-format msgid "" "download: %f\n" "upload: %f (kbit/s)" msgstr "" -#: ../gtk/incall_view.c:271 ../gtk/incall_view.c:272 +#: ../gtk/incall_view.c:272 ../gtk/incall_view.c:274 #, c-format -msgid "%ix%i" +msgid "%ix%i @ %f fps" msgstr "" -#: ../gtk/incall_view.c:301 +#: ../gtk/incall_view.c:304 #, c-format msgid "%.3f seconds" msgstr "" -#: ../gtk/incall_view.c:399 ../gtk/main.ui.h:12 +#: ../gtk/incall_view.c:407 ../gtk/main.ui.h:12 msgid "Hang up" msgstr "" -#: ../gtk/incall_view.c:492 +#: ../gtk/incall_view.c:501 #, fuzzy msgid "Calling..." msgstr "接続中" -#: ../gtk/incall_view.c:495 ../gtk/incall_view.c:698 +#: ../gtk/incall_view.c:504 ../gtk/incall_view.c:707 msgid "00::00::00" msgstr "" -#: ../gtk/incall_view.c:506 +#: ../gtk/incall_view.c:515 #, fuzzy msgid "Incoming call" msgstr "接続中" -#: ../gtk/incall_view.c:543 +#: ../gtk/incall_view.c:552 msgid "good" msgstr "" -#: ../gtk/incall_view.c:545 +#: ../gtk/incall_view.c:554 msgid "average" msgstr "" -#: ../gtk/incall_view.c:547 +#: ../gtk/incall_view.c:556 msgid "poor" msgstr "" -#: ../gtk/incall_view.c:549 +#: ../gtk/incall_view.c:558 msgid "very poor" msgstr "" -#: ../gtk/incall_view.c:551 +#: ../gtk/incall_view.c:560 msgid "too bad" msgstr "" -#: ../gtk/incall_view.c:552 ../gtk/incall_view.c:568 +#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:577 msgid "unavailable" msgstr "" -#: ../gtk/incall_view.c:660 +#: ../gtk/incall_view.c:669 msgid "Secured by SRTP" msgstr "" -#: ../gtk/incall_view.c:666 +#: ../gtk/incall_view.c:675 #, c-format msgid "Secured by ZRTP - [auth token: %s]" msgstr "" -#: ../gtk/incall_view.c:672 +#: ../gtk/incall_view.c:681 msgid "Set unverified" msgstr "" -#: ../gtk/incall_view.c:672 ../gtk/main.ui.h:4 +#: ../gtk/incall_view.c:681 ../gtk/main.ui.h:4 msgid "Set verified" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In conference" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 #, fuzzy msgid "In call" msgstr "接続中" -#: ../gtk/incall_view.c:729 +#: ../gtk/incall_view.c:738 #, fuzzy msgid "Paused call" msgstr "接続中" -#: ../gtk/incall_view.c:742 +#: ../gtk/incall_view.c:751 #, c-format msgid "%02i::%02i::%02i" msgstr "" -#: ../gtk/incall_view.c:760 +#: ../gtk/incall_view.c:772 #, fuzzy msgid "Call ended." msgstr "通話は拒否されました。" -#: ../gtk/incall_view.c:791 +#: ../gtk/incall_view.c:803 msgid "Transfer in progress" msgstr "" -#: ../gtk/incall_view.c:794 +#: ../gtk/incall_view.c:806 msgid "Transfer done." msgstr "" -#: ../gtk/incall_view.c:797 +#: ../gtk/incall_view.c:809 #, fuzzy msgid "Transfer failed." msgstr "通話はキャンセルされました。" -#: ../gtk/incall_view.c:841 +#: ../gtk/incall_view.c:853 msgid "Resume" msgstr "" -#: ../gtk/incall_view.c:848 ../gtk/main.ui.h:9 +#: ../gtk/incall_view.c:860 ../gtk/main.ui.h:9 msgid "Pause" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, c-format msgid "" "Recording into\n" "%s %s" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 msgid "(Paused)" msgstr "" @@ -794,64 +798,64 @@ msgstr "" msgid "Too loud" msgstr "" -#: ../gtk/audio_assistant.c:316 +#: ../gtk/audio_assistant.c:318 msgid "" "Welcome !\n" "This assistant will help you to configure audio settings for Linphone" msgstr "" -#: ../gtk/audio_assistant.c:326 +#: ../gtk/audio_assistant.c:328 #, fuzzy msgid "Capture device" msgstr "使用するサウンドデバイス" -#: ../gtk/audio_assistant.c:327 +#: ../gtk/audio_assistant.c:329 #, fuzzy msgid "Recorded volume" msgstr "録音する音源" -#: ../gtk/audio_assistant.c:331 +#: ../gtk/audio_assistant.c:333 msgid "No voice" msgstr "" -#: ../gtk/audio_assistant.c:367 +#: ../gtk/audio_assistant.c:369 #, fuzzy msgid "Playback device" msgstr "使用するサウンドデバイス" -#: ../gtk/audio_assistant.c:368 +#: ../gtk/audio_assistant.c:370 msgid "Play three beeps" msgstr "" -#: ../gtk/audio_assistant.c:400 +#: ../gtk/audio_assistant.c:403 msgid "Press the record button and say some words" msgstr "" -#: ../gtk/audio_assistant.c:401 +#: ../gtk/audio_assistant.c:404 msgid "Listen to your record voice" msgstr "" -#: ../gtk/audio_assistant.c:430 +#: ../gtk/audio_assistant.c:433 msgid "Let's start Linphone now" msgstr "" -#: ../gtk/audio_assistant.c:488 +#: ../gtk/audio_assistant.c:496 msgid "Audio Assistant" msgstr "" -#: ../gtk/audio_assistant.c:498 ../gtk/main.ui.h:31 +#: ../gtk/audio_assistant.c:506 ../gtk/main.ui.h:31 msgid "Audio assistant" msgstr "" -#: ../gtk/audio_assistant.c:503 +#: ../gtk/audio_assistant.c:511 msgid "Mic Gain calibration" msgstr "" -#: ../gtk/audio_assistant.c:509 +#: ../gtk/audio_assistant.c:517 msgid "Speaker volume calibration" msgstr "" -#: ../gtk/audio_assistant.c:514 +#: ../gtk/audio_assistant.c:522 msgid "Record and Play" msgstr "" @@ -1834,96 +1838,70 @@ msgstr "コネクション" msgid "Please wait while fetching configuration from server..." msgstr "" -#: ../coreapi/linphonecore.c:242 -msgid "aborted" -msgstr "" - -#: ../coreapi/linphonecore.c:245 -msgid "completed" -msgstr "" - -#: ../coreapi/linphonecore.c:248 -msgid "missed" -msgstr "" - -#: ../coreapi/linphonecore.c:253 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" - -#: ../coreapi/linphonecore.c:254 -msgid "Outgoing call" -msgstr "" - -#: ../coreapi/linphonecore.c:1287 +#: ../coreapi/linphonecore.c:1034 #, fuzzy msgid "Ready" msgstr "準備完了。" -#: ../coreapi/linphonecore.c:2248 +#: ../coreapi/linphonecore.c:1967 #, fuzzy msgid "Configuring" msgstr "情報" -#: ../coreapi/linphonecore.c:2410 +#: ../coreapi/linphonecore.c:2133 msgid "Looking for telephone number destination..." msgstr "" -#: ../coreapi/linphonecore.c:2413 +#: ../coreapi/linphonecore.c:2136 msgid "Could not resolve this number." msgstr "" #. must be known at that time -#: ../coreapi/linphonecore.c:2695 +#: ../coreapi/linphonecore.c:2418 #, fuzzy msgid "Contacting" msgstr "接続中" -#: ../coreapi/linphonecore.c:2702 +#: ../coreapi/linphonecore.c:2425 #, fuzzy msgid "Could not call" msgstr "pixmapファイルが見つかりません %s" -#: ../coreapi/linphonecore.c:2852 +#: ../coreapi/linphonecore.c:2576 msgid "Sorry, we have reached the maximum number of simultaneous calls" msgstr "" -#: ../coreapi/linphonecore.c:3022 +#: ../coreapi/linphonecore.c:2745 #, fuzzy msgid "is contacting you" msgstr "から電話です。" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid " and asked autoanswer." msgstr "" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid "." msgstr "" -#: ../coreapi/linphonecore.c:3139 +#: ../coreapi/linphonecore.c:2865 msgid "Modifying call parameters..." msgstr "" -#: ../coreapi/linphonecore.c:3469 +#: ../coreapi/linphonecore.c:3194 msgid "Connected." msgstr "接続しました。" -#: ../coreapi/linphonecore.c:3495 +#: ../coreapi/linphonecore.c:3220 #, fuzzy msgid "Call aborted" msgstr "通話はキャンセルされました。" -#: ../coreapi/linphonecore.c:3685 +#: ../coreapi/linphonecore.c:3412 msgid "Could not pause the call" msgstr "" -#: ../coreapi/linphonecore.c:3690 +#: ../coreapi/linphonecore.c:3417 msgid "Pausing the current call..." msgstr "" @@ -1992,143 +1970,143 @@ msgstr "情報" msgid "Unknown-bug" msgstr "" -#: ../coreapi/proxy.c:279 +#: ../coreapi/proxy.c:314 msgid "" "The sip proxy address you entered is invalid, it must start with \"sip:\" " "followed by a hostname." msgstr "" -#: ../coreapi/proxy.c:285 +#: ../coreapi/proxy.c:320 msgid "" "The sip identity you entered is invalid.\n" "It should look like sip:username@proxydomain, such as sip:alice@example.net" msgstr "" -#: ../coreapi/proxy.c:1299 +#: ../coreapi/proxy.c:1369 #, fuzzy, c-format msgid "Could not login as %s" msgstr "pixmapファイルが見つかりません %s" -#: ../coreapi/callbacks.c:354 +#: ../coreapi/callbacks.c:355 #, fuzzy msgid "Remote ringing." msgstr "登録中……" -#: ../coreapi/callbacks.c:370 +#: ../coreapi/callbacks.c:373 #, fuzzy msgid "Remote ringing..." msgstr "登録中……" -#: ../coreapi/callbacks.c:381 +#: ../coreapi/callbacks.c:384 msgid "Early media." msgstr "" -#: ../coreapi/callbacks.c:432 +#: ../coreapi/callbacks.c:435 #, c-format msgid "Call with %s is paused." msgstr "" -#: ../coreapi/callbacks.c:445 +#: ../coreapi/callbacks.c:448 #, c-format msgid "Call answered by %s - on hold." msgstr "" -#: ../coreapi/callbacks.c:456 +#: ../coreapi/callbacks.c:459 #, fuzzy msgid "Call resumed." msgstr "通話は拒否されました。" -#: ../coreapi/callbacks.c:461 +#: ../coreapi/callbacks.c:464 #, fuzzy, c-format msgid "Call answered by %s." msgstr "" "電話をかける\n" "電話に出る" -#: ../coreapi/callbacks.c:480 +#: ../coreapi/callbacks.c:483 msgid "Incompatible, check codecs or security settings..." msgstr "" -#: ../coreapi/callbacks.c:531 +#: ../coreapi/callbacks.c:512 msgid "We have been resumed." msgstr "" -#: ../coreapi/callbacks.c:541 +#: ../coreapi/callbacks.c:521 msgid "We are paused by other party." msgstr "" -#: ../coreapi/callbacks.c:558 +#: ../coreapi/callbacks.c:556 msgid "Call is updated by remote." msgstr "" -#: ../coreapi/callbacks.c:637 +#: ../coreapi/callbacks.c:658 #, fuzzy msgid "Call terminated." msgstr "通話は拒否されました。" -#: ../coreapi/callbacks.c:666 +#: ../coreapi/callbacks.c:687 msgid "User is busy." msgstr "ユーザーはビジーです" -#: ../coreapi/callbacks.c:667 +#: ../coreapi/callbacks.c:688 msgid "User is temporarily unavailable." msgstr "ユーザーは、今出られません。" #. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:669 +#: ../coreapi/callbacks.c:690 msgid "User does not want to be disturbed." msgstr "ユーザーは手が離せないようです。" -#: ../coreapi/callbacks.c:670 +#: ../coreapi/callbacks.c:691 msgid "Call declined." msgstr "通話は拒否されました。" -#: ../coreapi/callbacks.c:685 +#: ../coreapi/callbacks.c:706 msgid "Request timeout." msgstr "" -#: ../coreapi/callbacks.c:716 +#: ../coreapi/callbacks.c:737 msgid "Redirected" msgstr "" -#: ../coreapi/callbacks.c:766 +#: ../coreapi/callbacks.c:787 msgid "Incompatible media parameters." msgstr "" -#: ../coreapi/callbacks.c:777 +#: ../coreapi/callbacks.c:798 #, fuzzy msgid "Call failed." msgstr "通話はキャンセルされました。" -#: ../coreapi/callbacks.c:852 +#: ../coreapi/callbacks.c:878 #, fuzzy, c-format msgid "Registration on %s successful." msgstr "登録しました。" -#: ../coreapi/callbacks.c:853 +#: ../coreapi/callbacks.c:879 #, fuzzy, c-format msgid "Unregistration on %s done." msgstr "登録しました。" -#: ../coreapi/callbacks.c:875 +#: ../coreapi/callbacks.c:897 msgid "no response timeout" msgstr "" -#: ../coreapi/callbacks.c:878 +#: ../coreapi/callbacks.c:900 #, fuzzy, c-format msgid "Registration on %s failed: %s" msgstr "登録しました。" -#: ../coreapi/callbacks.c:885 +#: ../coreapi/callbacks.c:907 msgid "Service unavailable, retrying" msgstr "" -#: ../coreapi/linphonecall.c:175 +#: ../coreapi/linphonecall.c:177 #, fuzzy, c-format msgid "Authentication token is %s" msgstr "コーデックの情報" -#: ../coreapi/linphonecall.c:2994 +#: ../coreapi/linphonecall.c:2932 #, c-format msgid "You have missed %i call." msgid_plural "You have missed %i calls." diff --git a/po/nb_NO.po b/po/nb_NO.po index d135aecc6..6170997da 100644 --- a/po/nb_NO.po +++ b/po/nb_NO.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-01 21:24+0200\n" +"POT-Creation-Date: 2014-09-15 09:24+0200\n" "PO-Revision-Date: 2011-04-05 01:56+0200\n" "Last-Translator: Øyvind Sæther \n" "Language-Team: Norwegian Bokmål \n" @@ -17,12 +17,12 @@ msgstr "" "X-Generator: Lokalize 1.2\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:973 +#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:974 #, c-format msgid "Call %s" msgstr "Ring %s" -#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:974 +#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:975 #, c-format msgid "Send text to %s" msgstr "Send tekst til %s" @@ -32,52 +32,52 @@ msgstr "Send tekst til %s" msgid "Recent calls (%i)" msgstr "I samtale med" -#: ../gtk/calllogs.c:312 +#: ../gtk/calllogs.c:314 msgid "n/a" msgstr "" -#: ../gtk/calllogs.c:315 +#: ../gtk/calllogs.c:317 #, fuzzy msgid "Aborted" msgstr "avbrutt" -#: ../gtk/calllogs.c:318 +#: ../gtk/calllogs.c:320 #, fuzzy msgid "Missed" msgstr "ubesvart" -#: ../gtk/calllogs.c:321 +#: ../gtk/calllogs.c:323 #, fuzzy msgid "Declined" msgstr "Avvis" -#: ../gtk/calllogs.c:327 +#: ../gtk/calllogs.c:329 #, c-format msgid "%i minute" msgid_plural "%i minutes" msgstr[0] "" msgstr[1] "" -#: ../gtk/calllogs.c:330 +#: ../gtk/calllogs.c:332 #, c-format msgid "%i second" msgid_plural "%i seconds" msgstr[0] "" msgstr[1] "" -#: ../gtk/calllogs.c:333 ../gtk/calllogs.c:339 +#: ../gtk/calllogs.c:335 ../gtk/calllogs.c:341 #, c-format msgid "%s\t%s" msgstr "" -#: ../gtk/calllogs.c:335 +#: ../gtk/calllogs.c:337 #, c-format msgid "" "%s\tQuality: %s\n" "%s\t%s\t" msgstr "" -#: ../gtk/calllogs.c:341 +#: ../gtk/calllogs.c:343 #, c-format msgid "" "%s\t\n" @@ -98,7 +98,7 @@ msgstr "Skru mikrofonen av" msgid "Couldn't find pixmap file: %s" msgstr "Fant ikke pixmap fli: %s" -#: ../gtk/chat.c:363 ../gtk/friendlist.c:923 +#: ../gtk/chat.c:364 ../gtk/friendlist.c:924 msgid "Invalid sip contact !" msgstr "Ugyldig SIP kontakt !" @@ -149,7 +149,7 @@ msgstr "Brukerkontoveiviser" msgid "Call with %s" msgstr "Ring med %s" -#: ../gtk/main.c:1171 +#: ../gtk/main.c:1183 #, c-format msgid "" "%s would like to add you to his contact list.\n" @@ -162,7 +162,7 @@ msgstr "" "din kontaktliste?\n" "Hvis du svarer nei vil personen bli svartelyst midlertidig." -#: ../gtk/main.c:1248 +#: ../gtk/main.c:1260 #, fuzzy, c-format msgid "" "Please enter your password for username %s\n" @@ -171,61 +171,61 @@ msgstr "" "Skriv inn ditt passord for brukernavn %s\n" " på domene %s:i>:" -#: ../gtk/main.c:1364 +#: ../gtk/main.c:1376 #, fuzzy msgid "Call error" msgstr "Samtalehistorikk" -#: ../gtk/main.c:1367 ../coreapi/linphonecore.c:3515 +#: ../gtk/main.c:1379 ../coreapi/linphonecore.c:3240 msgid "Call ended" msgstr "Samtale avsluttet" -#: ../gtk/main.c:1370 ../coreapi/linphonecore.c:254 +#: ../gtk/main.c:1382 msgid "Incoming call" msgstr "Innkommende samtale" -#: ../gtk/main.c:1372 ../gtk/incall_view.c:513 ../gtk/main.ui.h:5 +#: ../gtk/main.c:1384 ../gtk/incall_view.c:522 ../gtk/main.ui.h:5 msgid "Answer" msgstr "Svarer" -#: ../gtk/main.c:1374 ../gtk/main.ui.h:6 +#: ../gtk/main.c:1386 ../gtk/main.ui.h:6 msgid "Decline" msgstr "Avvis" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy msgid "Call paused" msgstr "Samtale avbrutt" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy, c-format msgid "by %s" msgstr "Porter" -#: ../gtk/main.c:1447 +#: ../gtk/main.c:1459 #, c-format msgid "%s proposed to start video. Do you accept ?" msgstr "" -#: ../gtk/main.c:1609 +#: ../gtk/main.c:1621 msgid "Website link" msgstr "Peker til nettsted" -#: ../gtk/main.c:1658 +#: ../gtk/main.c:1670 msgid "Linphone - a video internet phone" msgstr "Linphone - en video Internet telefon" -#: ../gtk/main.c:1750 +#: ../gtk/main.c:1762 #, c-format msgid "%s (Default)" msgstr "%s (Standard)" -#: ../gtk/main.c:2086 ../coreapi/callbacks.c:927 +#: ../gtk/main.c:2099 ../coreapi/callbacks.c:949 #, c-format msgid "We are transferred to %s" msgstr "Vi er overført til %s" -#: ../gtk/main.c:2096 +#: ../gtk/main.c:2109 msgid "" "No sound cards have been detected on this computer.\n" "You won't be able to send or receive audio calls." @@ -233,7 +233,7 @@ msgstr "" "Klarte ikke å finne noe lydkort på denne datamaskinen.\n" "Du vil ikke kunne sende eller motta lydsamtaler." -#: ../gtk/main.c:2237 +#: ../gtk/main.c:2250 msgid "A free SIP video-phone" msgstr "En gratis SIP video-telefon" @@ -245,7 +245,7 @@ msgstr "" msgid "Presence status" msgstr "Tilstedestatus" -#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:550 ../gtk/contact.ui.h:1 +#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:552 ../gtk/contact.ui.h:1 msgid "Name" msgstr "Navn" @@ -263,141 +263,141 @@ msgstr "" msgid "Search in %s directory" msgstr "Søk i %s katalogen" -#: ../gtk/friendlist.c:975 +#: ../gtk/friendlist.c:976 #, c-format msgid "Edit contact '%s'" msgstr "Rediger kontakt '%s'" -#: ../gtk/friendlist.c:976 +#: ../gtk/friendlist.c:977 #, c-format msgid "Delete contact '%s'" msgstr "Slett kontakt '%s'" -#: ../gtk/friendlist.c:977 +#: ../gtk/friendlist.c:978 #, fuzzy, c-format msgid "Delete chat history of '%s'" msgstr "Slett kontakt '%s'" -#: ../gtk/friendlist.c:1028 +#: ../gtk/friendlist.c:1029 #, c-format msgid "Add new contact from %s directory" msgstr "Legg til kontakt fra %s katalogen" -#: ../gtk/propertybox.c:556 +#: ../gtk/propertybox.c:558 msgid "Rate (Hz)" msgstr "Frekvens (Hz)" -#: ../gtk/propertybox.c:562 +#: ../gtk/propertybox.c:564 msgid "Status" msgstr "Status" -#: ../gtk/propertybox.c:568 +#: ../gtk/propertybox.c:570 #, fuzzy msgid "IP Bitrate (kbit/s)" msgstr "Min. datahastighet (kbit/s)" -#: ../gtk/propertybox.c:575 +#: ../gtk/propertybox.c:577 msgid "Parameters" msgstr "Parametere" -#: ../gtk/propertybox.c:618 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:763 msgid "Enabled" msgstr "På" -#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:622 ../gtk/propertybox.c:763 msgid "Disabled" msgstr "Av" -#: ../gtk/propertybox.c:807 +#: ../gtk/propertybox.c:809 msgid "Account" msgstr "Konto" -#: ../gtk/propertybox.c:1061 +#: ../gtk/propertybox.c:1063 msgid "English" msgstr "Engelsk" -#: ../gtk/propertybox.c:1062 +#: ../gtk/propertybox.c:1064 msgid "French" msgstr "Fransk" -#: ../gtk/propertybox.c:1063 +#: ../gtk/propertybox.c:1065 msgid "Swedish" msgstr "Svensk" -#: ../gtk/propertybox.c:1064 +#: ../gtk/propertybox.c:1066 msgid "Italian" msgstr "Italisensk" -#: ../gtk/propertybox.c:1065 +#: ../gtk/propertybox.c:1067 msgid "Spanish" msgstr "Spansk" -#: ../gtk/propertybox.c:1066 +#: ../gtk/propertybox.c:1068 msgid "Brazilian Portugese" msgstr "Portugisisk" -#: ../gtk/propertybox.c:1067 +#: ../gtk/propertybox.c:1069 msgid "Polish" msgstr "Polsk" -#: ../gtk/propertybox.c:1068 +#: ../gtk/propertybox.c:1070 msgid "German" msgstr "Tysk" -#: ../gtk/propertybox.c:1069 +#: ../gtk/propertybox.c:1071 msgid "Russian" msgstr "Russisk" -#: ../gtk/propertybox.c:1070 +#: ../gtk/propertybox.c:1072 msgid "Japanese" msgstr "Japansk" -#: ../gtk/propertybox.c:1071 +#: ../gtk/propertybox.c:1073 msgid "Dutch" msgstr "Nederlandsk" -#: ../gtk/propertybox.c:1072 +#: ../gtk/propertybox.c:1074 msgid "Hungarian" msgstr "Ungarsk" -#: ../gtk/propertybox.c:1073 +#: ../gtk/propertybox.c:1075 msgid "Czech" msgstr "Tjekkisk" -#: ../gtk/propertybox.c:1074 +#: ../gtk/propertybox.c:1076 msgid "Chinese" msgstr "Kinesisk" -#: ../gtk/propertybox.c:1075 +#: ../gtk/propertybox.c:1077 msgid "Traditional Chinese" msgstr "" -#: ../gtk/propertybox.c:1076 +#: ../gtk/propertybox.c:1078 msgid "Norwegian" msgstr "" -#: ../gtk/propertybox.c:1077 +#: ../gtk/propertybox.c:1079 msgid "Hebrew" msgstr "" -#: ../gtk/propertybox.c:1078 +#: ../gtk/propertybox.c:1080 msgid "Serbian" msgstr "" -#: ../gtk/propertybox.c:1145 +#: ../gtk/propertybox.c:1147 msgid "" "You need to restart linphone for the new language selection to take effect." msgstr "Du må restarte linphone for at det nye språkvalget skal iverksettes." -#: ../gtk/propertybox.c:1223 +#: ../gtk/propertybox.c:1225 msgid "None" msgstr "" -#: ../gtk/propertybox.c:1227 +#: ../gtk/propertybox.c:1229 msgid "SRTP" msgstr "" -#: ../gtk/propertybox.c:1233 +#: ../gtk/propertybox.c:1235 msgid "ZRTP" msgstr "" @@ -472,110 +472,114 @@ msgstr "" msgid "Enter your linphone.org username" msgstr "" -#: ../gtk/setupwizard.c:96 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 +#: ../gtk/setupwizard.c:102 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 msgid "Username:" msgstr "Brukernavn:" -#: ../gtk/setupwizard.c:98 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 +#: ../gtk/setupwizard.c:104 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 msgid "Password:" msgstr "Passord:" -#: ../gtk/setupwizard.c:118 +#: ../gtk/setupwizard.c:124 msgid "Enter your account informations" msgstr "" -#: ../gtk/setupwizard.c:125 +#: ../gtk/setupwizard.c:140 #, fuzzy msgid "Username*" msgstr "Brukernavn" -#: ../gtk/setupwizard.c:126 +#: ../gtk/setupwizard.c:141 #, fuzzy msgid "Password*" msgstr "Passord" -#: ../gtk/setupwizard.c:129 +#: ../gtk/setupwizard.c:144 msgid "Domain*" msgstr "" -#: ../gtk/setupwizard.c:130 +#: ../gtk/setupwizard.c:145 msgid "Proxy" msgstr "" -#: ../gtk/setupwizard.c:302 +#: ../gtk/setupwizard.c:317 msgid "(*) Required fields" msgstr "" -#: ../gtk/setupwizard.c:303 +#: ../gtk/setupwizard.c:318 #, fuzzy msgid "Username: (*)" msgstr "Brukernavn:" -#: ../gtk/setupwizard.c:305 +#: ../gtk/setupwizard.c:320 #, fuzzy msgid "Password: (*)" msgstr "Passord:" -#: ../gtk/setupwizard.c:307 +#: ../gtk/setupwizard.c:322 msgid "Email: (*)" msgstr "" -#: ../gtk/setupwizard.c:309 +#: ../gtk/setupwizard.c:324 msgid "Confirm your password: (*)" msgstr "" -#: ../gtk/setupwizard.c:373 +#: ../gtk/setupwizard.c:338 +msgid "Keep me informed with linphone updates" +msgstr "" + +#: ../gtk/setupwizard.c:394 msgid "" "Error, account not validated, username already used or server unreachable.\n" "Please go back and try again." msgstr "" -#: ../gtk/setupwizard.c:384 +#: ../gtk/setupwizard.c:405 msgid "Thank you. Your account is now configured and ready for use." msgstr "Takk. Ditt konto er nå satt opp og klart til bruk." -#: ../gtk/setupwizard.c:392 +#: ../gtk/setupwizard.c:413 msgid "" "Please validate your account by clicking on the link we just sent you by " "email.\n" "Then come back here and press Next button." msgstr "" -#: ../gtk/setupwizard.c:564 +#: ../gtk/setupwizard.c:600 #, fuzzy msgid "SIP account configuration assistant" msgstr "Brukerkontoveiviser" -#: ../gtk/setupwizard.c:582 +#: ../gtk/setupwizard.c:618 msgid "Welcome to the account setup assistant" msgstr "Velkommen til brukerkontoveiviseren" -#: ../gtk/setupwizard.c:587 +#: ../gtk/setupwizard.c:623 msgid "Account setup assistant" msgstr "Brukerkontoveiviser" -#: ../gtk/setupwizard.c:593 +#: ../gtk/setupwizard.c:629 #, fuzzy msgid "Configure your account (step 1/1)" msgstr "Konfigurer en SIP konto" -#: ../gtk/setupwizard.c:598 +#: ../gtk/setupwizard.c:634 msgid "Enter your sip username (step 1/1)" msgstr "" -#: ../gtk/setupwizard.c:602 +#: ../gtk/setupwizard.c:638 msgid "Enter account information (step 1/2)" msgstr "" -#: ../gtk/setupwizard.c:611 +#: ../gtk/setupwizard.c:647 msgid "Validation (step 2/2)" msgstr "" -#: ../gtk/setupwizard.c:616 +#: ../gtk/setupwizard.c:652 msgid "Error" msgstr "" -#: ../gtk/setupwizard.c:620 ../gtk/audio_assistant.c:519 +#: ../gtk/setupwizard.c:656 ../gtk/audio_assistant.c:527 #, fuzzy msgid "Terminating" msgstr "Lägg på" @@ -647,131 +651,131 @@ msgstr "ICE filter" msgid "Direct or through server" msgstr "" -#: ../gtk/incall_view.c:266 ../gtk/incall_view.c:276 +#: ../gtk/incall_view.c:267 ../gtk/incall_view.c:279 #, c-format msgid "" "download: %f\n" "upload: %f (kbit/s)" msgstr "" -#: ../gtk/incall_view.c:271 ../gtk/incall_view.c:272 +#: ../gtk/incall_view.c:272 ../gtk/incall_view.c:274 #, c-format -msgid "%ix%i" +msgid "%ix%i @ %f fps" msgstr "" -#: ../gtk/incall_view.c:301 +#: ../gtk/incall_view.c:304 #, c-format msgid "%.3f seconds" msgstr "" -#: ../gtk/incall_view.c:399 ../gtk/main.ui.h:12 +#: ../gtk/incall_view.c:407 ../gtk/main.ui.h:12 msgid "Hang up" msgstr "" -#: ../gtk/incall_view.c:492 +#: ../gtk/incall_view.c:501 msgid "Calling..." msgstr "Ringer..." -#: ../gtk/incall_view.c:495 ../gtk/incall_view.c:698 +#: ../gtk/incall_view.c:504 ../gtk/incall_view.c:707 msgid "00::00::00" msgstr "00:00:00" -#: ../gtk/incall_view.c:506 +#: ../gtk/incall_view.c:515 msgid "Incoming call" msgstr "Innkommende samtale" -#: ../gtk/incall_view.c:543 +#: ../gtk/incall_view.c:552 msgid "good" msgstr "" -#: ../gtk/incall_view.c:545 +#: ../gtk/incall_view.c:554 msgid "average" msgstr "" -#: ../gtk/incall_view.c:547 +#: ../gtk/incall_view.c:556 msgid "poor" msgstr "" -#: ../gtk/incall_view.c:549 +#: ../gtk/incall_view.c:558 msgid "very poor" msgstr "" -#: ../gtk/incall_view.c:551 +#: ../gtk/incall_view.c:560 msgid "too bad" msgstr "" -#: ../gtk/incall_view.c:552 ../gtk/incall_view.c:568 +#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:577 msgid "unavailable" msgstr "" -#: ../gtk/incall_view.c:660 +#: ../gtk/incall_view.c:669 msgid "Secured by SRTP" msgstr "" -#: ../gtk/incall_view.c:666 +#: ../gtk/incall_view.c:675 #, c-format msgid "Secured by ZRTP - [auth token: %s]" msgstr "" -#: ../gtk/incall_view.c:672 +#: ../gtk/incall_view.c:681 msgid "Set unverified" msgstr "" -#: ../gtk/incall_view.c:672 ../gtk/main.ui.h:4 +#: ../gtk/incall_view.c:681 ../gtk/main.ui.h:4 msgid "Set verified" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In conference" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In call" msgstr "I samtale med" -#: ../gtk/incall_view.c:729 +#: ../gtk/incall_view.c:738 msgid "Paused call" msgstr "Pauset samtale" -#: ../gtk/incall_view.c:742 +#: ../gtk/incall_view.c:751 #, c-format msgid "%02i::%02i::%02i" msgstr "%02i:%02i:%02i" -#: ../gtk/incall_view.c:760 +#: ../gtk/incall_view.c:772 msgid "Call ended." msgstr "Samtale avsluttet." -#: ../gtk/incall_view.c:791 +#: ../gtk/incall_view.c:803 msgid "Transfer in progress" msgstr "" -#: ../gtk/incall_view.c:794 +#: ../gtk/incall_view.c:806 #, fuzzy msgid "Transfer done." msgstr "Overfører" -#: ../gtk/incall_view.c:797 +#: ../gtk/incall_view.c:809 #, fuzzy msgid "Transfer failed." msgstr "Overfører" -#: ../gtk/incall_view.c:841 +#: ../gtk/incall_view.c:853 msgid "Resume" msgstr "Fortsett" -#: ../gtk/incall_view.c:848 ../gtk/main.ui.h:9 +#: ../gtk/incall_view.c:860 ../gtk/main.ui.h:9 msgid "Pause" msgstr "Pause" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, c-format msgid "" "Recording into\n" "%s %s" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, fuzzy msgid "(Paused)" msgstr "Pause" @@ -807,7 +811,7 @@ msgstr "" msgid "Too loud" msgstr "" -#: ../gtk/audio_assistant.c:316 +#: ../gtk/audio_assistant.c:318 #, fuzzy msgid "" "Welcome !\n" @@ -816,59 +820,59 @@ msgstr "" "Velkommen\n" "Denne veiviseren vil hjelpe deg sette opp en SIP-konto for dine samtaler." -#: ../gtk/audio_assistant.c:326 +#: ../gtk/audio_assistant.c:328 #, fuzzy msgid "Capture device" msgstr "Mikrofonenhet:" -#: ../gtk/audio_assistant.c:327 +#: ../gtk/audio_assistant.c:329 msgid "Recorded volume" msgstr "" -#: ../gtk/audio_assistant.c:331 +#: ../gtk/audio_assistant.c:333 msgid "No voice" msgstr "" -#: ../gtk/audio_assistant.c:367 +#: ../gtk/audio_assistant.c:369 #, fuzzy msgid "Playback device" msgstr "Avspillingsenhet:" -#: ../gtk/audio_assistant.c:368 +#: ../gtk/audio_assistant.c:370 msgid "Play three beeps" msgstr "" -#: ../gtk/audio_assistant.c:400 +#: ../gtk/audio_assistant.c:403 msgid "Press the record button and say some words" msgstr "" -#: ../gtk/audio_assistant.c:401 +#: ../gtk/audio_assistant.c:404 msgid "Listen to your record voice" msgstr "" -#: ../gtk/audio_assistant.c:430 +#: ../gtk/audio_assistant.c:433 msgid "Let's start Linphone now" msgstr "" -#: ../gtk/audio_assistant.c:488 +#: ../gtk/audio_assistant.c:496 #, fuzzy msgid "Audio Assistant" msgstr "Assistent" -#: ../gtk/audio_assistant.c:498 ../gtk/main.ui.h:31 +#: ../gtk/audio_assistant.c:506 ../gtk/main.ui.h:31 #, fuzzy msgid "Audio assistant" msgstr "Brukerkontoveiviser" -#: ../gtk/audio_assistant.c:503 +#: ../gtk/audio_assistant.c:511 msgid "Mic Gain calibration" msgstr "" -#: ../gtk/audio_assistant.c:509 +#: ../gtk/audio_assistant.c:517 msgid "Speaker volume calibration" msgstr "" -#: ../gtk/audio_assistant.c:514 +#: ../gtk/audio_assistant.c:522 msgid "Record and Play" msgstr "" @@ -1824,96 +1828,65 @@ msgstr "Tilknytter..." msgid "Please wait while fetching configuration from server..." msgstr "" -#: ../coreapi/linphonecore.c:242 -msgid "aborted" -msgstr "avbrutt" - -#: ../coreapi/linphonecore.c:245 -msgid "completed" -msgstr "Fullført" - -#: ../coreapi/linphonecore.c:248 -msgid "missed" -msgstr "ubesvart" - -#: ../coreapi/linphonecore.c:253 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" -"%s på %s\n" -"Fra: %s\n" -"Til: %s\n" -"Status: %s\n" -"Lengde: %i min %i sek\n" - -#: ../coreapi/linphonecore.c:254 -msgid "Outgoing call" -msgstr "Utgående samtale" - -#: ../coreapi/linphonecore.c:1287 +#: ../coreapi/linphonecore.c:1034 msgid "Ready" msgstr "Klar" -#: ../coreapi/linphonecore.c:2248 +#: ../coreapi/linphonecore.c:1967 #, fuzzy msgid "Configuring" msgstr "Bekreftelse" -#: ../coreapi/linphonecore.c:2410 +#: ../coreapi/linphonecore.c:2133 msgid "Looking for telephone number destination..." msgstr "Ser etter telefonnummer for destinasjonen..." -#: ../coreapi/linphonecore.c:2413 +#: ../coreapi/linphonecore.c:2136 msgid "Could not resolve this number." msgstr "Kan ikke tilkoble dette nummeret." #. must be known at that time -#: ../coreapi/linphonecore.c:2695 +#: ../coreapi/linphonecore.c:2418 msgid "Contacting" msgstr "Tilknytter" -#: ../coreapi/linphonecore.c:2702 +#: ../coreapi/linphonecore.c:2425 msgid "Could not call" msgstr "Kunne ikke ringe" -#: ../coreapi/linphonecore.c:2852 +#: ../coreapi/linphonecore.c:2576 msgid "Sorry, we have reached the maximum number of simultaneous calls" msgstr "Beklager, du har nådd maksimalt antall samtidige samtaler" -#: ../coreapi/linphonecore.c:3022 +#: ../coreapi/linphonecore.c:2745 msgid "is contacting you" msgstr "Kontakter deg." -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid " and asked autoanswer." msgstr " og ba om autosvar." -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid "." msgstr "." -#: ../coreapi/linphonecore.c:3139 +#: ../coreapi/linphonecore.c:2865 msgid "Modifying call parameters..." msgstr "Endrer ringeparametre..." -#: ../coreapi/linphonecore.c:3469 +#: ../coreapi/linphonecore.c:3194 msgid "Connected." msgstr "Tilkoblet" -#: ../coreapi/linphonecore.c:3495 +#: ../coreapi/linphonecore.c:3220 msgid "Call aborted" msgstr "Samtale avbrutt" -#: ../coreapi/linphonecore.c:3685 +#: ../coreapi/linphonecore.c:3412 msgid "Could not pause the call" msgstr "Kunne ikke pause samtalen" -#: ../coreapi/linphonecore.c:3690 +#: ../coreapi/linphonecore.c:3417 msgid "Pausing the current call..." msgstr "Pauser nåværende samtale" @@ -1978,7 +1951,7 @@ msgstr "Varighet" msgid "Unknown-bug" msgstr "Ukjent feil" -#: ../coreapi/proxy.c:279 +#: ../coreapi/proxy.c:314 msgid "" "The sip proxy address you entered is invalid, it must start with \"sip:\" " "followed by a hostname." @@ -1986,7 +1959,7 @@ msgstr "" "SIP proxy adressen du har angitt er ugyldig, den må begynne med \"sip:\" " "etterfult av vertsnavn." -#: ../coreapi/proxy.c:285 +#: ../coreapi/proxy.c:320 msgid "" "The sip identity you entered is invalid.\n" "It should look like sip:username@proxydomain, such as sip:alice@example.net" @@ -1994,132 +1967,157 @@ msgstr "" "SIP adressen du har angitt er feil. Adressen bør se ut som sip: " "brukernavn@domenenavn, f.eks sip:ola@eksempel.no" -#: ../coreapi/proxy.c:1299 +#: ../coreapi/proxy.c:1369 #, c-format msgid "Could not login as %s" msgstr "Ikke ikke logge inn som %s" -#: ../coreapi/callbacks.c:354 +#: ../coreapi/callbacks.c:355 msgid "Remote ringing." msgstr "Ringer hos motparten." -#: ../coreapi/callbacks.c:370 +#: ../coreapi/callbacks.c:373 #, fuzzy msgid "Remote ringing..." msgstr "Ringer hos motparten." -#: ../coreapi/callbacks.c:381 +#: ../coreapi/callbacks.c:384 msgid "Early media." msgstr "Tidlig media" -#: ../coreapi/callbacks.c:432 +#: ../coreapi/callbacks.c:435 #, c-format msgid "Call with %s is paused." msgstr "Samtalen med %s er pauset." -#: ../coreapi/callbacks.c:445 +#: ../coreapi/callbacks.c:448 #, c-format msgid "Call answered by %s - on hold." msgstr "Samtale besvart av %s - på vent." -#: ../coreapi/callbacks.c:456 +#: ../coreapi/callbacks.c:459 msgid "Call resumed." msgstr "Samtale gjenopptatt." -#: ../coreapi/callbacks.c:461 +#: ../coreapi/callbacks.c:464 #, c-format msgid "Call answered by %s." msgstr "Samtale besvart av %s." -#: ../coreapi/callbacks.c:480 +#: ../coreapi/callbacks.c:483 msgid "Incompatible, check codecs or security settings..." msgstr "" -#: ../coreapi/callbacks.c:531 +#: ../coreapi/callbacks.c:512 #, fuzzy msgid "We have been resumed." msgstr "Vi har blitt gjenopptatt..." -#: ../coreapi/callbacks.c:541 +#: ../coreapi/callbacks.c:521 msgid "We are paused by other party." msgstr "" -#: ../coreapi/callbacks.c:558 +#: ../coreapi/callbacks.c:556 msgid "Call is updated by remote." msgstr "" -#: ../coreapi/callbacks.c:637 +#: ../coreapi/callbacks.c:658 msgid "Call terminated." msgstr "Samtale avsluttet." -#: ../coreapi/callbacks.c:666 +#: ../coreapi/callbacks.c:687 msgid "User is busy." msgstr "Brukeren er opptatt." -#: ../coreapi/callbacks.c:667 +#: ../coreapi/callbacks.c:688 msgid "User is temporarily unavailable." msgstr "Brukeren er midlertidig ikke tilgjengelig." #. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:669 +#: ../coreapi/callbacks.c:690 msgid "User does not want to be disturbed." msgstr "Brukeren vil ikke bli forstyrret." -#: ../coreapi/callbacks.c:670 +#: ../coreapi/callbacks.c:691 msgid "Call declined." msgstr "Samtale avvist." -#: ../coreapi/callbacks.c:685 +#: ../coreapi/callbacks.c:706 msgid "Request timeout." msgstr "" -#: ../coreapi/callbacks.c:716 +#: ../coreapi/callbacks.c:737 msgid "Redirected" msgstr "Omdirigert" -#: ../coreapi/callbacks.c:766 +#: ../coreapi/callbacks.c:787 msgid "Incompatible media parameters." msgstr "" -#: ../coreapi/callbacks.c:777 +#: ../coreapi/callbacks.c:798 msgid "Call failed." msgstr "Samtale feilet." -#: ../coreapi/callbacks.c:852 +#: ../coreapi/callbacks.c:878 #, c-format msgid "Registration on %s successful." msgstr "Registrering hos %s lykkes." -#: ../coreapi/callbacks.c:853 +#: ../coreapi/callbacks.c:879 #, c-format msgid "Unregistration on %s done." msgstr "Avregistrering hos %s lykkes." -#: ../coreapi/callbacks.c:875 +#: ../coreapi/callbacks.c:897 msgid "no response timeout" msgstr "ingen svar innen angitt tid" -#: ../coreapi/callbacks.c:878 +#: ../coreapi/callbacks.c:900 #, c-format msgid "Registration on %s failed: %s" msgstr "Registrering hos %s mislykkes: %s" -#: ../coreapi/callbacks.c:885 +#: ../coreapi/callbacks.c:907 msgid "Service unavailable, retrying" msgstr "" -#: ../coreapi/linphonecall.c:175 +#: ../coreapi/linphonecall.c:177 #, fuzzy, c-format msgid "Authentication token is %s" msgstr "Autorisering kreves" -#: ../coreapi/linphonecall.c:2994 +#: ../coreapi/linphonecall.c:2932 #, c-format msgid "You have missed %i call." msgid_plural "You have missed %i calls." msgstr[0] "Du har %i ubesvarte anrop." msgstr[1] "Du har %i missade samtal" +#~ msgid "aborted" +#~ msgstr "avbrutt" + +#~ msgid "completed" +#~ msgstr "Fullført" + +#~ msgid "missed" +#~ msgstr "ubesvart" + +#~ msgid "" +#~ "%s at %s\n" +#~ "From: %s\n" +#~ "To: %s\n" +#~ "Status: %s\n" +#~ "Duration: %i mn %i sec\n" +#~ msgstr "" +#~ "%s på %s\n" +#~ "Fra: %s\n" +#~ "Til: %s\n" +#~ "Status: %s\n" +#~ "Lengde: %i min %i sek\n" + +#~ msgid "Outgoing call" +#~ msgstr "Utgående samtale" + #~ msgid "No response." #~ msgstr "Ikke noe svar." diff --git a/po/nl.po b/po/nl.po index 21a4523cd..b650efb95 100644 --- a/po/nl.po +++ b/po/nl.po @@ -10,7 +10,7 @@ msgid "" msgstr "" "Project-Id-Version: nl\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-01 21:24+0200\n" +"POT-Creation-Date: 2014-09-15 09:24+0200\n" "PO-Revision-Date: 2007-09-05 10:40+0200\n" "Last-Translator: Hendrik-Jan Heins \n" "Language-Team: Nederlands \n" @@ -19,12 +19,12 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:973 +#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:974 #, fuzzy, c-format msgid "Call %s" msgstr "Oproepgeschiedenis" -#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:974 +#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:975 #, c-format msgid "Send text to %s" msgstr "" @@ -34,52 +34,52 @@ msgstr "" msgid "Recent calls (%i)" msgstr "Contactlijst" -#: ../gtk/calllogs.c:312 +#: ../gtk/calllogs.c:314 msgid "n/a" msgstr "" -#: ../gtk/calllogs.c:315 +#: ../gtk/calllogs.c:317 #, fuzzy msgid "Aborted" msgstr "afgebroken" -#: ../gtk/calllogs.c:318 +#: ../gtk/calllogs.c:320 #, fuzzy msgid "Missed" msgstr "gemist" -#: ../gtk/calllogs.c:321 +#: ../gtk/calllogs.c:323 #, fuzzy msgid "Declined" msgstr "lijn" -#: ../gtk/calllogs.c:327 +#: ../gtk/calllogs.c:329 #, c-format msgid "%i minute" msgid_plural "%i minutes" msgstr[0] "" msgstr[1] "" -#: ../gtk/calllogs.c:330 +#: ../gtk/calllogs.c:332 #, c-format msgid "%i second" msgid_plural "%i seconds" msgstr[0] "" msgstr[1] "" -#: ../gtk/calllogs.c:333 ../gtk/calllogs.c:339 +#: ../gtk/calllogs.c:335 ../gtk/calllogs.c:341 #, c-format msgid "%s\t%s" msgstr "" -#: ../gtk/calllogs.c:335 +#: ../gtk/calllogs.c:337 #, c-format msgid "" "%s\tQuality: %s\n" "%s\t%s\t" msgstr "" -#: ../gtk/calllogs.c:341 +#: ../gtk/calllogs.c:343 #, c-format msgid "" "%s\t\n" @@ -99,7 +99,7 @@ msgstr "" msgid "Couldn't find pixmap file: %s" msgstr "Kon pixmap bestand %s niet vinden" -#: ../gtk/chat.c:363 ../gtk/friendlist.c:923 +#: ../gtk/chat.c:364 ../gtk/friendlist.c:924 msgid "Invalid sip contact !" msgstr "" @@ -147,7 +147,7 @@ msgstr "" msgid "Call with %s" msgstr "Chat met %s" -#: ../gtk/main.c:1171 +#: ../gtk/main.c:1183 #, c-format msgid "" "%s would like to add you to his contact list.\n" @@ -156,75 +156,75 @@ msgid "" "If you answer no, this person will be temporarily blacklisted." msgstr "" -#: ../gtk/main.c:1248 +#: ../gtk/main.c:1260 #, c-format msgid "" "Please enter your password for username %s\n" " at realm %s:" msgstr "" -#: ../gtk/main.c:1364 +#: ../gtk/main.c:1376 #, fuzzy msgid "Call error" msgstr "Linphone - Oproepgeschiedenis" -#: ../gtk/main.c:1367 ../coreapi/linphonecore.c:3515 +#: ../gtk/main.c:1379 ../coreapi/linphonecore.c:3240 msgid "Call ended" msgstr "Oproep beeindigd" -#: ../gtk/main.c:1370 ../coreapi/linphonecore.c:254 +#: ../gtk/main.c:1382 msgid "Incoming call" msgstr "Inkomende oproep" -#: ../gtk/main.c:1372 ../gtk/incall_view.c:513 ../gtk/main.ui.h:5 +#: ../gtk/main.c:1384 ../gtk/incall_view.c:522 ../gtk/main.ui.h:5 msgid "Answer" msgstr "" -#: ../gtk/main.c:1374 ../gtk/main.ui.h:6 +#: ../gtk/main.c:1386 ../gtk/main.ui.h:6 #, fuzzy msgid "Decline" msgstr "lijn" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy msgid "Call paused" msgstr "afgebroken" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy, c-format msgid "by %s" msgstr "Contactlijst" -#: ../gtk/main.c:1447 +#: ../gtk/main.c:1459 #, c-format msgid "%s proposed to start video. Do you accept ?" msgstr "" -#: ../gtk/main.c:1609 +#: ../gtk/main.c:1621 msgid "Website link" msgstr "" -#: ../gtk/main.c:1658 +#: ../gtk/main.c:1670 msgid "Linphone - a video internet phone" msgstr "" -#: ../gtk/main.c:1750 +#: ../gtk/main.c:1762 #, c-format msgid "%s (Default)" msgstr "" -#: ../gtk/main.c:2086 ../coreapi/callbacks.c:927 +#: ../gtk/main.c:2099 ../coreapi/callbacks.c:949 #, c-format msgid "We are transferred to %s" msgstr "" -#: ../gtk/main.c:2096 +#: ../gtk/main.c:2109 msgid "" "No sound cards have been detected on this computer.\n" "You won't be able to send or receive audio calls." msgstr "" -#: ../gtk/main.c:2237 +#: ../gtk/main.c:2250 msgid "A free SIP video-phone" msgstr "Een Vrije SIP video-telefoon" @@ -237,7 +237,7 @@ msgstr "Adresboek" msgid "Presence status" msgstr "Aanwezigheidsstatus" -#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:550 ../gtk/contact.ui.h:1 +#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:552 ../gtk/contact.ui.h:1 msgid "Name" msgstr "Naam" @@ -256,141 +256,141 @@ msgstr "Chat box" msgid "Search in %s directory" msgstr "" -#: ../gtk/friendlist.c:975 +#: ../gtk/friendlist.c:976 #, fuzzy, c-format msgid "Edit contact '%s'" msgstr "Bewerk contactgegevens" -#: ../gtk/friendlist.c:976 +#: ../gtk/friendlist.c:977 #, c-format msgid "Delete contact '%s'" msgstr "" -#: ../gtk/friendlist.c:977 +#: ../gtk/friendlist.c:978 #, c-format msgid "Delete chat history of '%s'" msgstr "" -#: ../gtk/friendlist.c:1028 +#: ../gtk/friendlist.c:1029 #, c-format msgid "Add new contact from %s directory" msgstr "" -#: ../gtk/propertybox.c:556 +#: ../gtk/propertybox.c:558 msgid "Rate (Hz)" msgstr "Frequentie (Hz)" -#: ../gtk/propertybox.c:562 +#: ../gtk/propertybox.c:564 msgid "Status" msgstr "Status" -#: ../gtk/propertybox.c:568 +#: ../gtk/propertybox.c:570 #, fuzzy msgid "IP Bitrate (kbit/s)" msgstr "Minimale bitrate (kbit/s)" -#: ../gtk/propertybox.c:575 +#: ../gtk/propertybox.c:577 msgid "Parameters" msgstr "Parameters" -#: ../gtk/propertybox.c:618 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:763 msgid "Enabled" msgstr "Aan" -#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:622 ../gtk/propertybox.c:763 msgid "Disabled" msgstr "Uit" -#: ../gtk/propertybox.c:807 +#: ../gtk/propertybox.c:809 msgid "Account" msgstr "Account" -#: ../gtk/propertybox.c:1061 +#: ../gtk/propertybox.c:1063 msgid "English" msgstr "" -#: ../gtk/propertybox.c:1062 +#: ../gtk/propertybox.c:1064 msgid "French" msgstr "" -#: ../gtk/propertybox.c:1063 +#: ../gtk/propertybox.c:1065 msgid "Swedish" msgstr "" -#: ../gtk/propertybox.c:1064 +#: ../gtk/propertybox.c:1066 msgid "Italian" msgstr "" -#: ../gtk/propertybox.c:1065 +#: ../gtk/propertybox.c:1067 msgid "Spanish" msgstr "" -#: ../gtk/propertybox.c:1066 +#: ../gtk/propertybox.c:1068 msgid "Brazilian Portugese" msgstr "" -#: ../gtk/propertybox.c:1067 +#: ../gtk/propertybox.c:1069 msgid "Polish" msgstr "" -#: ../gtk/propertybox.c:1068 +#: ../gtk/propertybox.c:1070 msgid "German" msgstr "" -#: ../gtk/propertybox.c:1069 +#: ../gtk/propertybox.c:1071 msgid "Russian" msgstr "" -#: ../gtk/propertybox.c:1070 +#: ../gtk/propertybox.c:1072 msgid "Japanese" msgstr "" -#: ../gtk/propertybox.c:1071 +#: ../gtk/propertybox.c:1073 msgid "Dutch" msgstr "" -#: ../gtk/propertybox.c:1072 +#: ../gtk/propertybox.c:1074 msgid "Hungarian" msgstr "" -#: ../gtk/propertybox.c:1073 +#: ../gtk/propertybox.c:1075 msgid "Czech" msgstr "" -#: ../gtk/propertybox.c:1074 +#: ../gtk/propertybox.c:1076 msgid "Chinese" msgstr "" -#: ../gtk/propertybox.c:1075 +#: ../gtk/propertybox.c:1077 msgid "Traditional Chinese" msgstr "" -#: ../gtk/propertybox.c:1076 +#: ../gtk/propertybox.c:1078 msgid "Norwegian" msgstr "" -#: ../gtk/propertybox.c:1077 +#: ../gtk/propertybox.c:1079 msgid "Hebrew" msgstr "" -#: ../gtk/propertybox.c:1078 +#: ../gtk/propertybox.c:1080 msgid "Serbian" msgstr "" -#: ../gtk/propertybox.c:1145 +#: ../gtk/propertybox.c:1147 msgid "" "You need to restart linphone for the new language selection to take effect." msgstr "" -#: ../gtk/propertybox.c:1223 +#: ../gtk/propertybox.c:1225 msgid "None" msgstr "Geen" -#: ../gtk/propertybox.c:1227 +#: ../gtk/propertybox.c:1229 msgid "SRTP" msgstr "" -#: ../gtk/propertybox.c:1233 +#: ../gtk/propertybox.c:1235 msgid "ZRTP" msgstr "" @@ -460,110 +460,114 @@ msgstr "" msgid "Enter your linphone.org username" msgstr "" -#: ../gtk/setupwizard.c:96 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 +#: ../gtk/setupwizard.c:102 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 #, fuzzy msgid "Username:" msgstr "gebruikersnaam:" -#: ../gtk/setupwizard.c:98 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 +#: ../gtk/setupwizard.c:104 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 #, fuzzy msgid "Password:" msgstr "wachtwoord:" -#: ../gtk/setupwizard.c:118 +#: ../gtk/setupwizard.c:124 msgid "Enter your account informations" msgstr "" -#: ../gtk/setupwizard.c:125 +#: ../gtk/setupwizard.c:140 #, fuzzy msgid "Username*" msgstr "gebruikersnaam:" -#: ../gtk/setupwizard.c:126 +#: ../gtk/setupwizard.c:141 #, fuzzy msgid "Password*" msgstr "wachtwoord:" -#: ../gtk/setupwizard.c:129 +#: ../gtk/setupwizard.c:144 msgid "Domain*" msgstr "" -#: ../gtk/setupwizard.c:130 +#: ../gtk/setupwizard.c:145 msgid "Proxy" msgstr "" -#: ../gtk/setupwizard.c:302 +#: ../gtk/setupwizard.c:317 msgid "(*) Required fields" msgstr "" -#: ../gtk/setupwizard.c:303 +#: ../gtk/setupwizard.c:318 #, fuzzy msgid "Username: (*)" msgstr "gebruikersnaam:" -#: ../gtk/setupwizard.c:305 +#: ../gtk/setupwizard.c:320 #, fuzzy msgid "Password: (*)" msgstr "wachtwoord:" -#: ../gtk/setupwizard.c:307 +#: ../gtk/setupwizard.c:322 msgid "Email: (*)" msgstr "" -#: ../gtk/setupwizard.c:309 +#: ../gtk/setupwizard.c:324 msgid "Confirm your password: (*)" msgstr "" -#: ../gtk/setupwizard.c:373 +#: ../gtk/setupwizard.c:338 +msgid "Keep me informed with linphone updates" +msgstr "" + +#: ../gtk/setupwizard.c:394 msgid "" "Error, account not validated, username already used or server unreachable.\n" "Please go back and try again." msgstr "" -#: ../gtk/setupwizard.c:384 +#: ../gtk/setupwizard.c:405 msgid "Thank you. Your account is now configured and ready for use." msgstr "" -#: ../gtk/setupwizard.c:392 +#: ../gtk/setupwizard.c:413 msgid "" "Please validate your account by clicking on the link we just sent you by " "email.\n" "Then come back here and press Next button." msgstr "" -#: ../gtk/setupwizard.c:564 +#: ../gtk/setupwizard.c:600 msgid "SIP account configuration assistant" msgstr "" -#: ../gtk/setupwizard.c:582 +#: ../gtk/setupwizard.c:618 msgid "Welcome to the account setup assistant" msgstr "" -#: ../gtk/setupwizard.c:587 +#: ../gtk/setupwizard.c:623 msgid "Account setup assistant" msgstr "" -#: ../gtk/setupwizard.c:593 +#: ../gtk/setupwizard.c:629 msgid "Configure your account (step 1/1)" msgstr "" -#: ../gtk/setupwizard.c:598 +#: ../gtk/setupwizard.c:634 msgid "Enter your sip username (step 1/1)" msgstr "" -#: ../gtk/setupwizard.c:602 +#: ../gtk/setupwizard.c:638 msgid "Enter account information (step 1/2)" msgstr "" -#: ../gtk/setupwizard.c:611 +#: ../gtk/setupwizard.c:647 msgid "Validation (step 2/2)" msgstr "" -#: ../gtk/setupwizard.c:616 +#: ../gtk/setupwizard.c:652 msgid "Error" msgstr "" -#: ../gtk/setupwizard.c:620 ../gtk/audio_assistant.c:519 +#: ../gtk/setupwizard.c:656 ../gtk/audio_assistant.c:527 msgid "Terminating" msgstr "" @@ -634,135 +638,135 @@ msgstr "Oproep geannuleerd." msgid "Direct or through server" msgstr "" -#: ../gtk/incall_view.c:266 ../gtk/incall_view.c:276 +#: ../gtk/incall_view.c:267 ../gtk/incall_view.c:279 #, c-format msgid "" "download: %f\n" "upload: %f (kbit/s)" msgstr "" -#: ../gtk/incall_view.c:271 ../gtk/incall_view.c:272 +#: ../gtk/incall_view.c:272 ../gtk/incall_view.c:274 #, c-format -msgid "%ix%i" +msgid "%ix%i @ %f fps" msgstr "" -#: ../gtk/incall_view.c:301 +#: ../gtk/incall_view.c:304 #, c-format msgid "%.3f seconds" msgstr "" -#: ../gtk/incall_view.c:399 ../gtk/main.ui.h:12 +#: ../gtk/incall_view.c:407 ../gtk/main.ui.h:12 msgid "Hang up" msgstr "" -#: ../gtk/incall_view.c:492 +#: ../gtk/incall_view.c:501 #, fuzzy msgid "Calling..." msgstr "Contactlijst" -#: ../gtk/incall_view.c:495 ../gtk/incall_view.c:698 +#: ../gtk/incall_view.c:504 ../gtk/incall_view.c:707 msgid "00::00::00" msgstr "" -#: ../gtk/incall_view.c:506 +#: ../gtk/incall_view.c:515 #, fuzzy msgid "Incoming call" msgstr "Inkomende oproep" -#: ../gtk/incall_view.c:543 +#: ../gtk/incall_view.c:552 msgid "good" msgstr "" -#: ../gtk/incall_view.c:545 +#: ../gtk/incall_view.c:554 msgid "average" msgstr "" -#: ../gtk/incall_view.c:547 +#: ../gtk/incall_view.c:556 msgid "poor" msgstr "" -#: ../gtk/incall_view.c:549 +#: ../gtk/incall_view.c:558 msgid "very poor" msgstr "" -#: ../gtk/incall_view.c:551 +#: ../gtk/incall_view.c:560 msgid "too bad" msgstr "" -#: ../gtk/incall_view.c:552 ../gtk/incall_view.c:568 +#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:577 msgid "unavailable" msgstr "" -#: ../gtk/incall_view.c:660 +#: ../gtk/incall_view.c:669 msgid "Secured by SRTP" msgstr "" -#: ../gtk/incall_view.c:666 +#: ../gtk/incall_view.c:675 #, c-format msgid "Secured by ZRTP - [auth token: %s]" msgstr "" -#: ../gtk/incall_view.c:672 +#: ../gtk/incall_view.c:681 msgid "Set unverified" msgstr "" -#: ../gtk/incall_view.c:672 ../gtk/main.ui.h:4 +#: ../gtk/incall_view.c:681 ../gtk/main.ui.h:4 msgid "Set verified" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In conference" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 #, fuzzy msgid "In call" msgstr "Contactlijst" -#: ../gtk/incall_view.c:729 +#: ../gtk/incall_view.c:738 #, fuzzy msgid "Paused call" msgstr "Contactlijst" -#: ../gtk/incall_view.c:742 +#: ../gtk/incall_view.c:751 #, c-format msgid "%02i::%02i::%02i" msgstr "" -#: ../gtk/incall_view.c:760 +#: ../gtk/incall_view.c:772 #, fuzzy msgid "Call ended." msgstr "Oproep beeindigd" -#: ../gtk/incall_view.c:791 +#: ../gtk/incall_view.c:803 msgid "Transfer in progress" msgstr "" -#: ../gtk/incall_view.c:794 +#: ../gtk/incall_view.c:806 msgid "Transfer done." msgstr "" -#: ../gtk/incall_view.c:797 +#: ../gtk/incall_view.c:809 #, fuzzy msgid "Transfer failed." msgstr "Oproep geannuleerd." -#: ../gtk/incall_view.c:841 +#: ../gtk/incall_view.c:853 msgid "Resume" msgstr "" -#: ../gtk/incall_view.c:848 ../gtk/main.ui.h:9 +#: ../gtk/incall_view.c:860 ../gtk/main.ui.h:9 msgid "Pause" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, c-format msgid "" "Recording into\n" "%s %s" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 msgid "(Paused)" msgstr "" @@ -797,64 +801,64 @@ msgstr "" msgid "Too loud" msgstr "" -#: ../gtk/audio_assistant.c:316 +#: ../gtk/audio_assistant.c:318 msgid "" "Welcome !\n" "This assistant will help you to configure audio settings for Linphone" msgstr "" -#: ../gtk/audio_assistant.c:326 +#: ../gtk/audio_assistant.c:328 #, fuzzy msgid "Capture device" msgstr "Geluidsapparaat gebruiken:" -#: ../gtk/audio_assistant.c:327 +#: ../gtk/audio_assistant.c:329 #, fuzzy msgid "Recorded volume" msgstr "Bron voor opname:" -#: ../gtk/audio_assistant.c:331 +#: ../gtk/audio_assistant.c:333 msgid "No voice" msgstr "" -#: ../gtk/audio_assistant.c:367 +#: ../gtk/audio_assistant.c:369 #, fuzzy msgid "Playback device" msgstr "Geluidsapparaat gebruiken:" -#: ../gtk/audio_assistant.c:368 +#: ../gtk/audio_assistant.c:370 msgid "Play three beeps" msgstr "" -#: ../gtk/audio_assistant.c:400 +#: ../gtk/audio_assistant.c:403 msgid "Press the record button and say some words" msgstr "" -#: ../gtk/audio_assistant.c:401 +#: ../gtk/audio_assistant.c:404 msgid "Listen to your record voice" msgstr "" -#: ../gtk/audio_assistant.c:430 +#: ../gtk/audio_assistant.c:433 msgid "Let's start Linphone now" msgstr "" -#: ../gtk/audio_assistant.c:488 +#: ../gtk/audio_assistant.c:496 msgid "Audio Assistant" msgstr "" -#: ../gtk/audio_assistant.c:498 ../gtk/main.ui.h:31 +#: ../gtk/audio_assistant.c:506 ../gtk/main.ui.h:31 msgid "Audio assistant" msgstr "" -#: ../gtk/audio_assistant.c:503 +#: ../gtk/audio_assistant.c:511 msgid "Mic Gain calibration" msgstr "" -#: ../gtk/audio_assistant.c:509 +#: ../gtk/audio_assistant.c:517 msgid "Speaker volume calibration" msgstr "" -#: ../gtk/audio_assistant.c:514 +#: ../gtk/audio_assistant.c:522 msgid "Record and Play" msgstr "" @@ -1847,100 +1851,69 @@ msgstr "Verbinden" msgid "Please wait while fetching configuration from server..." msgstr "" -#: ../coreapi/linphonecore.c:242 -msgid "aborted" -msgstr "afgebroken" - -#: ../coreapi/linphonecore.c:245 -msgid "completed" -msgstr "voltooid" - -#: ../coreapi/linphonecore.c:248 -msgid "missed" -msgstr "gemist" - -#: ../coreapi/linphonecore.c:253 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" -"%s op %s\n" -"Van: %s\n" -"Aan: %s\n" -"Status: %s\n" -"Tijdsduur: %i mins %i secs\n" - -#: ../coreapi/linphonecore.c:254 -msgid "Outgoing call" -msgstr "Uitgaande oproep" - -#: ../coreapi/linphonecore.c:1287 +#: ../coreapi/linphonecore.c:1034 msgid "Ready" msgstr "Gereed." -#: ../coreapi/linphonecore.c:2248 +#: ../coreapi/linphonecore.c:1967 #, fuzzy msgid "Configuring" msgstr "Informatie" -#: ../coreapi/linphonecore.c:2410 +#: ../coreapi/linphonecore.c:2133 msgid "Looking for telephone number destination..." msgstr "Zoekt de lokatie van het telefoonnummer..." -#: ../coreapi/linphonecore.c:2413 +#: ../coreapi/linphonecore.c:2136 msgid "Could not resolve this number." msgstr "Kon dit nummer niet vinden." #. must be known at that time -#: ../coreapi/linphonecore.c:2695 +#: ../coreapi/linphonecore.c:2418 msgid "Contacting" msgstr "Verbinden" -#: ../coreapi/linphonecore.c:2702 +#: ../coreapi/linphonecore.c:2425 #, fuzzy msgid "Could not call" msgstr "Kon niet oproepen" -#: ../coreapi/linphonecore.c:2852 +#: ../coreapi/linphonecore.c:2576 msgid "Sorry, we have reached the maximum number of simultaneous calls" msgstr "" -#: ../coreapi/linphonecore.c:3022 +#: ../coreapi/linphonecore.c:2745 #, fuzzy msgid "is contacting you" msgstr "belt u." -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid " and asked autoanswer." msgstr "" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid "." msgstr "" -#: ../coreapi/linphonecore.c:3139 +#: ../coreapi/linphonecore.c:2865 msgid "Modifying call parameters..." msgstr "" -#: ../coreapi/linphonecore.c:3469 +#: ../coreapi/linphonecore.c:3194 msgid "Connected." msgstr "Verbonden." -#: ../coreapi/linphonecore.c:3495 +#: ../coreapi/linphonecore.c:3220 #, fuzzy msgid "Call aborted" msgstr "afgebroken" -#: ../coreapi/linphonecore.c:3685 +#: ../coreapi/linphonecore.c:3412 #, fuzzy msgid "Could not pause the call" msgstr "Kon niet oproepen" -#: ../coreapi/linphonecore.c:3690 +#: ../coreapi/linphonecore.c:3417 #, fuzzy msgid "Pausing the current call..." msgstr "Kon niet oproepen" @@ -2011,149 +1984,174 @@ msgstr "Informatie" msgid "Unknown-bug" msgstr "" -#: ../coreapi/proxy.c:279 +#: ../coreapi/proxy.c:314 msgid "" "The sip proxy address you entered is invalid, it must start with \"sip:\" " "followed by a hostname." msgstr "" -#: ../coreapi/proxy.c:285 +#: ../coreapi/proxy.c:320 msgid "" "The sip identity you entered is invalid.\n" "It should look like sip:username@proxydomain, such as sip:alice@example.net" msgstr "" -#: ../coreapi/proxy.c:1299 +#: ../coreapi/proxy.c:1369 #, fuzzy, c-format msgid "Could not login as %s" msgstr "Kon pixmap bestand %s niet vinden" -#: ../coreapi/callbacks.c:354 +#: ../coreapi/callbacks.c:355 #, fuzzy msgid "Remote ringing." msgstr "Externe diensten" -#: ../coreapi/callbacks.c:370 +#: ../coreapi/callbacks.c:373 #, fuzzy msgid "Remote ringing..." msgstr "Externe diensten" -#: ../coreapi/callbacks.c:381 +#: ../coreapi/callbacks.c:384 msgid "Early media." msgstr "" -#: ../coreapi/callbacks.c:432 +#: ../coreapi/callbacks.c:435 #, fuzzy, c-format msgid "Call with %s is paused." msgstr "Chat met %s" -#: ../coreapi/callbacks.c:445 +#: ../coreapi/callbacks.c:448 #, c-format msgid "Call answered by %s - on hold." msgstr "" -#: ../coreapi/callbacks.c:456 +#: ../coreapi/callbacks.c:459 #, fuzzy msgid "Call resumed." msgstr "Oproep beeindigd" -#: ../coreapi/callbacks.c:461 +#: ../coreapi/callbacks.c:464 #, fuzzy, c-format msgid "Call answered by %s." msgstr "" "Oproepen of\n" "beantwoorden" -#: ../coreapi/callbacks.c:480 +#: ../coreapi/callbacks.c:483 msgid "Incompatible, check codecs or security settings..." msgstr "" -#: ../coreapi/callbacks.c:531 +#: ../coreapi/callbacks.c:512 msgid "We have been resumed." msgstr "" -#: ../coreapi/callbacks.c:541 +#: ../coreapi/callbacks.c:521 msgid "We are paused by other party." msgstr "" -#: ../coreapi/callbacks.c:558 +#: ../coreapi/callbacks.c:556 msgid "Call is updated by remote." msgstr "" -#: ../coreapi/callbacks.c:637 +#: ../coreapi/callbacks.c:658 msgid "Call terminated." msgstr "Oproep beeindigd." -#: ../coreapi/callbacks.c:666 +#: ../coreapi/callbacks.c:687 msgid "User is busy." msgstr "Gebruiker is bezet." -#: ../coreapi/callbacks.c:667 +#: ../coreapi/callbacks.c:688 msgid "User is temporarily unavailable." msgstr "Gebruiker is tijdelijk niet beschikbaar." #. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:669 +#: ../coreapi/callbacks.c:690 msgid "User does not want to be disturbed." msgstr "De gebruiker wenst niet gestoord te worden." -#: ../coreapi/callbacks.c:670 +#: ../coreapi/callbacks.c:691 msgid "Call declined." msgstr "Oproep geweigerd." -#: ../coreapi/callbacks.c:685 +#: ../coreapi/callbacks.c:706 msgid "Request timeout." msgstr "" -#: ../coreapi/callbacks.c:716 +#: ../coreapi/callbacks.c:737 #, fuzzy msgid "Redirected" msgstr "Doorgeschakeld naar %s..." -#: ../coreapi/callbacks.c:766 +#: ../coreapi/callbacks.c:787 msgid "Incompatible media parameters." msgstr "" -#: ../coreapi/callbacks.c:777 +#: ../coreapi/callbacks.c:798 #, fuzzy msgid "Call failed." msgstr "Oproep geannuleerd." -#: ../coreapi/callbacks.c:852 +#: ../coreapi/callbacks.c:878 #, c-format msgid "Registration on %s successful." msgstr "Registratie op %s gelukt." -#: ../coreapi/callbacks.c:853 +#: ../coreapi/callbacks.c:879 #, fuzzy, c-format msgid "Unregistration on %s done." msgstr "Registratie op %s gelukt." -#: ../coreapi/callbacks.c:875 +#: ../coreapi/callbacks.c:897 msgid "no response timeout" msgstr "" -#: ../coreapi/callbacks.c:878 +#: ../coreapi/callbacks.c:900 #, fuzzy, c-format msgid "Registration on %s failed: %s" msgstr "Registratie op %s mislukt (time-out)." -#: ../coreapi/callbacks.c:885 +#: ../coreapi/callbacks.c:907 msgid "Service unavailable, retrying" msgstr "" -#: ../coreapi/linphonecall.c:175 +#: ../coreapi/linphonecall.c:177 #, fuzzy, c-format msgid "Authentication token is %s" msgstr "Authorisatie gegevens" -#: ../coreapi/linphonecall.c:2994 +#: ../coreapi/linphonecall.c:2932 #, fuzzy, c-format msgid "You have missed %i call." msgid_plural "You have missed %i calls." msgstr[0] "U heeft %i oproep(en) gemist." msgstr[1] "U heeft %i oproep(en) gemist." +#~ msgid "aborted" +#~ msgstr "afgebroken" + +#~ msgid "completed" +#~ msgstr "voltooid" + +#~ msgid "missed" +#~ msgstr "gemist" + +#~ msgid "" +#~ "%s at %s\n" +#~ "From: %s\n" +#~ "To: %s\n" +#~ "Status: %s\n" +#~ "Duration: %i mn %i sec\n" +#~ msgstr "" +#~ "%s op %s\n" +#~ "Van: %s\n" +#~ "Aan: %s\n" +#~ "Status: %s\n" +#~ "Tijdsduur: %i mins %i secs\n" + +#~ msgid "Outgoing call" +#~ msgstr "Uitgaande oproep" + #~ msgid "" #~ "Could not parse given sip address. A sip url usually looks like sip:" #~ "user@domain" diff --git a/po/pl.po b/po/pl.po index 819c7ab7e..62e06d793 100644 --- a/po/pl.po +++ b/po/pl.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: linphone 0.7.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-01 21:24+0200\n" +"POT-Creation-Date: 2014-09-15 09:24+0200\n" "PO-Revision-Date: 2003-08-22 12:50+0200\n" "Last-Translator: Robert Nasiadek \n" "Language-Team: Polski \n" @@ -15,12 +15,12 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8-bit\n" -#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:973 +#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:974 #, c-format msgid "Call %s" msgstr "" -#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:974 +#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:975 #, c-format msgid "Send text to %s" msgstr "" @@ -30,51 +30,51 @@ msgstr "" msgid "Recent calls (%i)" msgstr "Dzwonie do " -#: ../gtk/calllogs.c:312 +#: ../gtk/calllogs.c:314 msgid "n/a" msgstr "" -#: ../gtk/calllogs.c:315 +#: ../gtk/calllogs.c:317 #, fuzzy msgid "Aborted" msgstr "Połączenie odwołane." -#: ../gtk/calllogs.c:318 +#: ../gtk/calllogs.c:320 msgid "Missed" msgstr "" -#: ../gtk/calllogs.c:321 +#: ../gtk/calllogs.c:323 #, fuzzy msgid "Declined" msgstr "linia" -#: ../gtk/calllogs.c:327 +#: ../gtk/calllogs.c:329 #, c-format msgid "%i minute" msgid_plural "%i minutes" msgstr[0] "" msgstr[1] "" -#: ../gtk/calllogs.c:330 +#: ../gtk/calllogs.c:332 #, c-format msgid "%i second" msgid_plural "%i seconds" msgstr[0] "" msgstr[1] "" -#: ../gtk/calllogs.c:333 ../gtk/calllogs.c:339 +#: ../gtk/calllogs.c:335 ../gtk/calllogs.c:341 #, c-format msgid "%s\t%s" msgstr "" -#: ../gtk/calllogs.c:335 +#: ../gtk/calllogs.c:337 #, c-format msgid "" "%s\tQuality: %s\n" "%s\t%s\t" msgstr "" -#: ../gtk/calllogs.c:341 +#: ../gtk/calllogs.c:343 #, c-format msgid "" "%s\t\n" @@ -94,7 +94,7 @@ msgstr "" msgid "Couldn't find pixmap file: %s" msgstr "Nie można znaleźć pixmapy: %s" -#: ../gtk/chat.c:363 ../gtk/friendlist.c:923 +#: ../gtk/chat.c:364 ../gtk/friendlist.c:924 msgid "Invalid sip contact !" msgstr "" @@ -142,7 +142,7 @@ msgstr "" msgid "Call with %s" msgstr "" -#: ../gtk/main.c:1171 +#: ../gtk/main.c:1183 #, c-format msgid "" "%s would like to add you to his contact list.\n" @@ -151,76 +151,76 @@ msgid "" "If you answer no, this person will be temporarily blacklisted." msgstr "" -#: ../gtk/main.c:1248 +#: ../gtk/main.c:1260 #, c-format msgid "" "Please enter your password for username %s\n" " at realm %s:" msgstr "" -#: ../gtk/main.c:1364 +#: ../gtk/main.c:1376 #, fuzzy msgid "Call error" msgstr "Połączenie odwołane." -#: ../gtk/main.c:1367 ../coreapi/linphonecore.c:3515 +#: ../gtk/main.c:1379 ../coreapi/linphonecore.c:3240 #, fuzzy msgid "Call ended" msgstr "Rozmowa odrzucona." -#: ../gtk/main.c:1370 ../coreapi/linphonecore.c:254 +#: ../gtk/main.c:1382 msgid "Incoming call" msgstr "" -#: ../gtk/main.c:1372 ../gtk/incall_view.c:513 ../gtk/main.ui.h:5 +#: ../gtk/main.c:1384 ../gtk/incall_view.c:522 ../gtk/main.ui.h:5 msgid "Answer" msgstr "" -#: ../gtk/main.c:1374 ../gtk/main.ui.h:6 +#: ../gtk/main.c:1386 ../gtk/main.ui.h:6 #, fuzzy msgid "Decline" msgstr "linia" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy msgid "Call paused" msgstr "Połączenie odwołane." -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy, c-format msgid "by %s" msgstr "Dzwonie do " -#: ../gtk/main.c:1447 +#: ../gtk/main.c:1459 #, c-format msgid "%s proposed to start video. Do you accept ?" msgstr "" -#: ../gtk/main.c:1609 +#: ../gtk/main.c:1621 msgid "Website link" msgstr "" -#: ../gtk/main.c:1658 +#: ../gtk/main.c:1670 msgid "Linphone - a video internet phone" msgstr "" -#: ../gtk/main.c:1750 +#: ../gtk/main.c:1762 #, c-format msgid "%s (Default)" msgstr "" -#: ../gtk/main.c:2086 ../coreapi/callbacks.c:927 +#: ../gtk/main.c:2099 ../coreapi/callbacks.c:949 #, c-format msgid "We are transferred to %s" msgstr "" -#: ../gtk/main.c:2096 +#: ../gtk/main.c:2109 msgid "" "No sound cards have been detected on this computer.\n" "You won't be able to send or receive audio calls." msgstr "" -#: ../gtk/main.c:2237 +#: ../gtk/main.c:2250 msgid "A free SIP video-phone" msgstr "" @@ -234,7 +234,7 @@ msgstr "Książka adresowa" msgid "Presence status" msgstr "Obecność" -#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:550 ../gtk/contact.ui.h:1 +#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:552 ../gtk/contact.ui.h:1 msgid "Name" msgstr "Nazwa" @@ -252,142 +252,142 @@ msgstr "" msgid "Search in %s directory" msgstr "" -#: ../gtk/friendlist.c:975 +#: ../gtk/friendlist.c:976 #, fuzzy, c-format msgid "Edit contact '%s'" msgstr "(Brak informacji kontaktowych !)" -#: ../gtk/friendlist.c:976 +#: ../gtk/friendlist.c:977 #, c-format msgid "Delete contact '%s'" msgstr "" -#: ../gtk/friendlist.c:977 +#: ../gtk/friendlist.c:978 #, c-format msgid "Delete chat history of '%s'" msgstr "" -#: ../gtk/friendlist.c:1028 +#: ../gtk/friendlist.c:1029 #, c-format msgid "Add new contact from %s directory" msgstr "" -#: ../gtk/propertybox.c:556 +#: ../gtk/propertybox.c:558 msgid "Rate (Hz)" msgstr "Jakość (Hz)" -#: ../gtk/propertybox.c:562 +#: ../gtk/propertybox.c:564 msgid "Status" msgstr "Status" -#: ../gtk/propertybox.c:568 +#: ../gtk/propertybox.c:570 #, fuzzy msgid "IP Bitrate (kbit/s)" msgstr "Min przepustowość (kbit/s)" -#: ../gtk/propertybox.c:575 +#: ../gtk/propertybox.c:577 msgid "Parameters" msgstr "Parametr" -#: ../gtk/propertybox.c:618 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:763 msgid "Enabled" msgstr "Włączone" -#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:622 ../gtk/propertybox.c:763 msgid "Disabled" msgstr "Wyłączone" -#: ../gtk/propertybox.c:807 +#: ../gtk/propertybox.c:809 msgid "Account" msgstr "" -#: ../gtk/propertybox.c:1061 +#: ../gtk/propertybox.c:1063 msgid "English" msgstr "" -#: ../gtk/propertybox.c:1062 +#: ../gtk/propertybox.c:1064 msgid "French" msgstr "" -#: ../gtk/propertybox.c:1063 +#: ../gtk/propertybox.c:1065 msgid "Swedish" msgstr "" -#: ../gtk/propertybox.c:1064 +#: ../gtk/propertybox.c:1066 msgid "Italian" msgstr "" -#: ../gtk/propertybox.c:1065 +#: ../gtk/propertybox.c:1067 msgid "Spanish" msgstr "" -#: ../gtk/propertybox.c:1066 +#: ../gtk/propertybox.c:1068 msgid "Brazilian Portugese" msgstr "" -#: ../gtk/propertybox.c:1067 +#: ../gtk/propertybox.c:1069 msgid "Polish" msgstr "" -#: ../gtk/propertybox.c:1068 +#: ../gtk/propertybox.c:1070 msgid "German" msgstr "" -#: ../gtk/propertybox.c:1069 +#: ../gtk/propertybox.c:1071 msgid "Russian" msgstr "" -#: ../gtk/propertybox.c:1070 +#: ../gtk/propertybox.c:1072 msgid "Japanese" msgstr "" -#: ../gtk/propertybox.c:1071 +#: ../gtk/propertybox.c:1073 msgid "Dutch" msgstr "" -#: ../gtk/propertybox.c:1072 +#: ../gtk/propertybox.c:1074 msgid "Hungarian" msgstr "" -#: ../gtk/propertybox.c:1073 +#: ../gtk/propertybox.c:1075 msgid "Czech" msgstr "" -#: ../gtk/propertybox.c:1074 +#: ../gtk/propertybox.c:1076 msgid "Chinese" msgstr "" -#: ../gtk/propertybox.c:1075 +#: ../gtk/propertybox.c:1077 msgid "Traditional Chinese" msgstr "" -#: ../gtk/propertybox.c:1076 +#: ../gtk/propertybox.c:1078 msgid "Norwegian" msgstr "" -#: ../gtk/propertybox.c:1077 +#: ../gtk/propertybox.c:1079 msgid "Hebrew" msgstr "" -#: ../gtk/propertybox.c:1078 +#: ../gtk/propertybox.c:1080 msgid "Serbian" msgstr "" -#: ../gtk/propertybox.c:1145 +#: ../gtk/propertybox.c:1147 msgid "" "You need to restart linphone for the new language selection to take effect." msgstr "" -#: ../gtk/propertybox.c:1223 +#: ../gtk/propertybox.c:1225 #, fuzzy msgid "None" msgstr "Brak." -#: ../gtk/propertybox.c:1227 +#: ../gtk/propertybox.c:1229 msgid "SRTP" msgstr "" -#: ../gtk/propertybox.c:1233 +#: ../gtk/propertybox.c:1235 msgid "ZRTP" msgstr "" @@ -457,110 +457,114 @@ msgstr "" msgid "Enter your linphone.org username" msgstr "" -#: ../gtk/setupwizard.c:96 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 +#: ../gtk/setupwizard.c:102 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 #, fuzzy msgid "Username:" msgstr "Podręcznik" -#: ../gtk/setupwizard.c:98 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 +#: ../gtk/setupwizard.c:104 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 #, fuzzy msgid "Password:" msgstr "Twoje hasło:" -#: ../gtk/setupwizard.c:118 +#: ../gtk/setupwizard.c:124 msgid "Enter your account informations" msgstr "" -#: ../gtk/setupwizard.c:125 +#: ../gtk/setupwizard.c:140 #, fuzzy msgid "Username*" msgstr "Podręcznik" -#: ../gtk/setupwizard.c:126 +#: ../gtk/setupwizard.c:141 #, fuzzy msgid "Password*" msgstr "Twoje hasło:" -#: ../gtk/setupwizard.c:129 +#: ../gtk/setupwizard.c:144 msgid "Domain*" msgstr "" -#: ../gtk/setupwizard.c:130 +#: ../gtk/setupwizard.c:145 msgid "Proxy" msgstr "" -#: ../gtk/setupwizard.c:302 +#: ../gtk/setupwizard.c:317 msgid "(*) Required fields" msgstr "" -#: ../gtk/setupwizard.c:303 +#: ../gtk/setupwizard.c:318 #, fuzzy msgid "Username: (*)" msgstr "Podręcznik" -#: ../gtk/setupwizard.c:305 +#: ../gtk/setupwizard.c:320 #, fuzzy msgid "Password: (*)" msgstr "Twoje hasło:" -#: ../gtk/setupwizard.c:307 +#: ../gtk/setupwizard.c:322 msgid "Email: (*)" msgstr "" -#: ../gtk/setupwizard.c:309 +#: ../gtk/setupwizard.c:324 msgid "Confirm your password: (*)" msgstr "" -#: ../gtk/setupwizard.c:373 +#: ../gtk/setupwizard.c:338 +msgid "Keep me informed with linphone updates" +msgstr "" + +#: ../gtk/setupwizard.c:394 msgid "" "Error, account not validated, username already used or server unreachable.\n" "Please go back and try again." msgstr "" -#: ../gtk/setupwizard.c:384 +#: ../gtk/setupwizard.c:405 msgid "Thank you. Your account is now configured and ready for use." msgstr "" -#: ../gtk/setupwizard.c:392 +#: ../gtk/setupwizard.c:413 msgid "" "Please validate your account by clicking on the link we just sent you by " "email.\n" "Then come back here and press Next button." msgstr "" -#: ../gtk/setupwizard.c:564 +#: ../gtk/setupwizard.c:600 msgid "SIP account configuration assistant" msgstr "" -#: ../gtk/setupwizard.c:582 +#: ../gtk/setupwizard.c:618 msgid "Welcome to the account setup assistant" msgstr "" -#: ../gtk/setupwizard.c:587 +#: ../gtk/setupwizard.c:623 msgid "Account setup assistant" msgstr "" -#: ../gtk/setupwizard.c:593 +#: ../gtk/setupwizard.c:629 msgid "Configure your account (step 1/1)" msgstr "" -#: ../gtk/setupwizard.c:598 +#: ../gtk/setupwizard.c:634 msgid "Enter your sip username (step 1/1)" msgstr "" -#: ../gtk/setupwizard.c:602 +#: ../gtk/setupwizard.c:638 msgid "Enter account information (step 1/2)" msgstr "" -#: ../gtk/setupwizard.c:611 +#: ../gtk/setupwizard.c:647 msgid "Validation (step 2/2)" msgstr "" -#: ../gtk/setupwizard.c:616 +#: ../gtk/setupwizard.c:652 msgid "Error" msgstr "" -#: ../gtk/setupwizard.c:620 ../gtk/audio_assistant.c:519 +#: ../gtk/setupwizard.c:656 ../gtk/audio_assistant.c:527 msgid "Terminating" msgstr "" @@ -629,135 +633,135 @@ msgstr "Połączenie odwołane." msgid "Direct or through server" msgstr "" -#: ../gtk/incall_view.c:266 ../gtk/incall_view.c:276 +#: ../gtk/incall_view.c:267 ../gtk/incall_view.c:279 #, c-format msgid "" "download: %f\n" "upload: %f (kbit/s)" msgstr "" -#: ../gtk/incall_view.c:271 ../gtk/incall_view.c:272 +#: ../gtk/incall_view.c:272 ../gtk/incall_view.c:274 #, c-format -msgid "%ix%i" +msgid "%ix%i @ %f fps" msgstr "" -#: ../gtk/incall_view.c:301 +#: ../gtk/incall_view.c:304 #, c-format msgid "%.3f seconds" msgstr "" -#: ../gtk/incall_view.c:399 ../gtk/main.ui.h:12 +#: ../gtk/incall_view.c:407 ../gtk/main.ui.h:12 msgid "Hang up" msgstr "" -#: ../gtk/incall_view.c:492 +#: ../gtk/incall_view.c:501 #, fuzzy msgid "Calling..." msgstr "Dzwonie do " -#: ../gtk/incall_view.c:495 ../gtk/incall_view.c:698 +#: ../gtk/incall_view.c:504 ../gtk/incall_view.c:707 msgid "00::00::00" msgstr "" -#: ../gtk/incall_view.c:506 +#: ../gtk/incall_view.c:515 #, fuzzy msgid "Incoming call" msgstr "Dzwonie do " -#: ../gtk/incall_view.c:543 +#: ../gtk/incall_view.c:552 msgid "good" msgstr "" -#: ../gtk/incall_view.c:545 +#: ../gtk/incall_view.c:554 msgid "average" msgstr "" -#: ../gtk/incall_view.c:547 +#: ../gtk/incall_view.c:556 msgid "poor" msgstr "" -#: ../gtk/incall_view.c:549 +#: ../gtk/incall_view.c:558 msgid "very poor" msgstr "" -#: ../gtk/incall_view.c:551 +#: ../gtk/incall_view.c:560 msgid "too bad" msgstr "" -#: ../gtk/incall_view.c:552 ../gtk/incall_view.c:568 +#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:577 msgid "unavailable" msgstr "" -#: ../gtk/incall_view.c:660 +#: ../gtk/incall_view.c:669 msgid "Secured by SRTP" msgstr "" -#: ../gtk/incall_view.c:666 +#: ../gtk/incall_view.c:675 #, c-format msgid "Secured by ZRTP - [auth token: %s]" msgstr "" -#: ../gtk/incall_view.c:672 +#: ../gtk/incall_view.c:681 msgid "Set unverified" msgstr "" -#: ../gtk/incall_view.c:672 ../gtk/main.ui.h:4 +#: ../gtk/incall_view.c:681 ../gtk/main.ui.h:4 msgid "Set verified" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In conference" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 #, fuzzy msgid "In call" msgstr "Dzwonie do " -#: ../gtk/incall_view.c:729 +#: ../gtk/incall_view.c:738 #, fuzzy msgid "Paused call" msgstr "Dzwonie do " -#: ../gtk/incall_view.c:742 +#: ../gtk/incall_view.c:751 #, c-format msgid "%02i::%02i::%02i" msgstr "" -#: ../gtk/incall_view.c:760 +#: ../gtk/incall_view.c:772 #, fuzzy msgid "Call ended." msgstr "Rozmowa odrzucona." -#: ../gtk/incall_view.c:791 +#: ../gtk/incall_view.c:803 msgid "Transfer in progress" msgstr "" -#: ../gtk/incall_view.c:794 +#: ../gtk/incall_view.c:806 msgid "Transfer done." msgstr "" -#: ../gtk/incall_view.c:797 +#: ../gtk/incall_view.c:809 #, fuzzy msgid "Transfer failed." msgstr "Połączenie odwołane." -#: ../gtk/incall_view.c:841 +#: ../gtk/incall_view.c:853 msgid "Resume" msgstr "" -#: ../gtk/incall_view.c:848 ../gtk/main.ui.h:9 +#: ../gtk/incall_view.c:860 ../gtk/main.ui.h:9 msgid "Pause" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, c-format msgid "" "Recording into\n" "%s %s" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 msgid "(Paused)" msgstr "" @@ -792,64 +796,64 @@ msgstr "" msgid "Too loud" msgstr "" -#: ../gtk/audio_assistant.c:316 +#: ../gtk/audio_assistant.c:318 msgid "" "Welcome !\n" "This assistant will help you to configure audio settings for Linphone" msgstr "" -#: ../gtk/audio_assistant.c:326 +#: ../gtk/audio_assistant.c:328 #, fuzzy msgid "Capture device" msgstr "Użyj tego urządzenia dźwięku:" -#: ../gtk/audio_assistant.c:327 +#: ../gtk/audio_assistant.c:329 #, fuzzy msgid "Recorded volume" msgstr "Źródło nagrywania:" -#: ../gtk/audio_assistant.c:331 +#: ../gtk/audio_assistant.c:333 msgid "No voice" msgstr "" -#: ../gtk/audio_assistant.c:367 +#: ../gtk/audio_assistant.c:369 #, fuzzy msgid "Playback device" msgstr "Użyj tego urządzenia dźwięku:" -#: ../gtk/audio_assistant.c:368 +#: ../gtk/audio_assistant.c:370 msgid "Play three beeps" msgstr "" -#: ../gtk/audio_assistant.c:400 +#: ../gtk/audio_assistant.c:403 msgid "Press the record button and say some words" msgstr "" -#: ../gtk/audio_assistant.c:401 +#: ../gtk/audio_assistant.c:404 msgid "Listen to your record voice" msgstr "" -#: ../gtk/audio_assistant.c:430 +#: ../gtk/audio_assistant.c:433 msgid "Let's start Linphone now" msgstr "" -#: ../gtk/audio_assistant.c:488 +#: ../gtk/audio_assistant.c:496 msgid "Audio Assistant" msgstr "" -#: ../gtk/audio_assistant.c:498 ../gtk/main.ui.h:31 +#: ../gtk/audio_assistant.c:506 ../gtk/main.ui.h:31 msgid "Audio assistant" msgstr "" -#: ../gtk/audio_assistant.c:503 +#: ../gtk/audio_assistant.c:511 msgid "Mic Gain calibration" msgstr "" -#: ../gtk/audio_assistant.c:509 +#: ../gtk/audio_assistant.c:517 msgid "Speaker volume calibration" msgstr "" -#: ../gtk/audio_assistant.c:514 +#: ../gtk/audio_assistant.c:522 msgid "Record and Play" msgstr "" @@ -1833,96 +1837,70 @@ msgstr "Lącze" msgid "Please wait while fetching configuration from server..." msgstr "" -#: ../coreapi/linphonecore.c:242 -msgid "aborted" -msgstr "" - -#: ../coreapi/linphonecore.c:245 -msgid "completed" -msgstr "" - -#: ../coreapi/linphonecore.c:248 -msgid "missed" -msgstr "" - -#: ../coreapi/linphonecore.c:253 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" - -#: ../coreapi/linphonecore.c:254 -msgid "Outgoing call" -msgstr "" - -#: ../coreapi/linphonecore.c:1287 +#: ../coreapi/linphonecore.c:1034 #, fuzzy msgid "Ready" msgstr "Gotowy." -#: ../coreapi/linphonecore.c:2248 +#: ../coreapi/linphonecore.c:1967 #, fuzzy msgid "Configuring" msgstr "Informacja" -#: ../coreapi/linphonecore.c:2410 +#: ../coreapi/linphonecore.c:2133 msgid "Looking for telephone number destination..." msgstr "" -#: ../coreapi/linphonecore.c:2413 +#: ../coreapi/linphonecore.c:2136 msgid "Could not resolve this number." msgstr "" #. must be known at that time -#: ../coreapi/linphonecore.c:2695 +#: ../coreapi/linphonecore.c:2418 #, fuzzy msgid "Contacting" msgstr "Dzwonie do " -#: ../coreapi/linphonecore.c:2702 +#: ../coreapi/linphonecore.c:2425 #, fuzzy msgid "Could not call" msgstr "Nie można znaleźć pixmapy: %s" -#: ../coreapi/linphonecore.c:2852 +#: ../coreapi/linphonecore.c:2576 msgid "Sorry, we have reached the maximum number of simultaneous calls" msgstr "" -#: ../coreapi/linphonecore.c:3022 +#: ../coreapi/linphonecore.c:2745 #, fuzzy msgid "is contacting you" msgstr "dzwoni do Ciebie." -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid " and asked autoanswer." msgstr "" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid "." msgstr "" -#: ../coreapi/linphonecore.c:3139 +#: ../coreapi/linphonecore.c:2865 msgid "Modifying call parameters..." msgstr "" -#: ../coreapi/linphonecore.c:3469 +#: ../coreapi/linphonecore.c:3194 msgid "Connected." msgstr "Połączony" -#: ../coreapi/linphonecore.c:3495 +#: ../coreapi/linphonecore.c:3220 #, fuzzy msgid "Call aborted" msgstr "Połączenie odwołane." -#: ../coreapi/linphonecore.c:3685 +#: ../coreapi/linphonecore.c:3412 msgid "Could not pause the call" msgstr "" -#: ../coreapi/linphonecore.c:3690 +#: ../coreapi/linphonecore.c:3417 msgid "Pausing the current call..." msgstr "" @@ -1991,143 +1969,143 @@ msgstr "Informacja" msgid "Unknown-bug" msgstr "" -#: ../coreapi/proxy.c:279 +#: ../coreapi/proxy.c:314 msgid "" "The sip proxy address you entered is invalid, it must start with \"sip:\" " "followed by a hostname." msgstr "" -#: ../coreapi/proxy.c:285 +#: ../coreapi/proxy.c:320 msgid "" "The sip identity you entered is invalid.\n" "It should look like sip:username@proxydomain, such as sip:alice@example.net" msgstr "" -#: ../coreapi/proxy.c:1299 +#: ../coreapi/proxy.c:1369 #, fuzzy, c-format msgid "Could not login as %s" msgstr "Nie można znaleźć pixmapy: %s" -#: ../coreapi/callbacks.c:354 +#: ../coreapi/callbacks.c:355 #, fuzzy msgid "Remote ringing." msgstr "Rejestruje..." -#: ../coreapi/callbacks.c:370 +#: ../coreapi/callbacks.c:373 #, fuzzy msgid "Remote ringing..." msgstr "Rejestruje..." -#: ../coreapi/callbacks.c:381 +#: ../coreapi/callbacks.c:384 msgid "Early media." msgstr "" -#: ../coreapi/callbacks.c:432 +#: ../coreapi/callbacks.c:435 #, c-format msgid "Call with %s is paused." msgstr "" -#: ../coreapi/callbacks.c:445 +#: ../coreapi/callbacks.c:448 #, c-format msgid "Call answered by %s - on hold." msgstr "" -#: ../coreapi/callbacks.c:456 +#: ../coreapi/callbacks.c:459 #, fuzzy msgid "Call resumed." msgstr "Rozmowa odrzucona." -#: ../coreapi/callbacks.c:461 +#: ../coreapi/callbacks.c:464 #, fuzzy, c-format msgid "Call answered by %s." msgstr "" "Zadzwoń lub\n" "Odpowiedz" -#: ../coreapi/callbacks.c:480 +#: ../coreapi/callbacks.c:483 msgid "Incompatible, check codecs or security settings..." msgstr "" -#: ../coreapi/callbacks.c:531 +#: ../coreapi/callbacks.c:512 msgid "We have been resumed." msgstr "" -#: ../coreapi/callbacks.c:541 +#: ../coreapi/callbacks.c:521 msgid "We are paused by other party." msgstr "" -#: ../coreapi/callbacks.c:558 +#: ../coreapi/callbacks.c:556 msgid "Call is updated by remote." msgstr "" -#: ../coreapi/callbacks.c:637 +#: ../coreapi/callbacks.c:658 #, fuzzy msgid "Call terminated." msgstr "Rozmowa odrzucona." -#: ../coreapi/callbacks.c:666 +#: ../coreapi/callbacks.c:687 msgid "User is busy." msgstr "Osoba jest zajęta." -#: ../coreapi/callbacks.c:667 +#: ../coreapi/callbacks.c:688 msgid "User is temporarily unavailable." msgstr "Osoba jest tymczasowo niedostępna." #. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:669 +#: ../coreapi/callbacks.c:690 msgid "User does not want to be disturbed." msgstr "Osoba nie chce, aby jej przeszkadzać." -#: ../coreapi/callbacks.c:670 +#: ../coreapi/callbacks.c:691 msgid "Call declined." msgstr "Rozmowa odrzucona." -#: ../coreapi/callbacks.c:685 +#: ../coreapi/callbacks.c:706 msgid "Request timeout." msgstr "" -#: ../coreapi/callbacks.c:716 +#: ../coreapi/callbacks.c:737 msgid "Redirected" msgstr "" -#: ../coreapi/callbacks.c:766 +#: ../coreapi/callbacks.c:787 msgid "Incompatible media parameters." msgstr "" -#: ../coreapi/callbacks.c:777 +#: ../coreapi/callbacks.c:798 #, fuzzy msgid "Call failed." msgstr "Połączenie odwołane." -#: ../coreapi/callbacks.c:852 +#: ../coreapi/callbacks.c:878 #, fuzzy, c-format msgid "Registration on %s successful." msgstr "Rejestracja powiodła się." -#: ../coreapi/callbacks.c:853 +#: ../coreapi/callbacks.c:879 #, fuzzy, c-format msgid "Unregistration on %s done." msgstr "Rejestracja powiodła się." -#: ../coreapi/callbacks.c:875 +#: ../coreapi/callbacks.c:897 msgid "no response timeout" msgstr "" -#: ../coreapi/callbacks.c:878 +#: ../coreapi/callbacks.c:900 #, fuzzy, c-format msgid "Registration on %s failed: %s" msgstr "Rejestracja powiodła się." -#: ../coreapi/callbacks.c:885 +#: ../coreapi/callbacks.c:907 msgid "Service unavailable, retrying" msgstr "" -#: ../coreapi/linphonecall.c:175 +#: ../coreapi/linphonecall.c:177 #, fuzzy, c-format msgid "Authentication token is %s" msgstr "Informacje o kodeku" -#: ../coreapi/linphonecall.c:2994 +#: ../coreapi/linphonecall.c:2932 #, c-format msgid "You have missed %i call." msgid_plural "You have missed %i calls." diff --git a/po/pt_BR.po b/po/pt_BR.po index 21b309da3..c30d3787a 100644 --- a/po/pt_BR.po +++ b/po/pt_BR.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: linphone-1.1.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-01 21:24+0200\n" +"POT-Creation-Date: 2014-09-15 09:24+0200\n" "PO-Revision-Date: 2006-07-11 23:30+0200\n" "Last-Translator: Rafael Caesar Lenzi \n" "Language-Team: pt_BR \n" @@ -17,12 +17,12 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:973 +#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:974 #, fuzzy, c-format msgid "Call %s" msgstr "Histórico de chamadas" -#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:974 +#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:975 #, c-format msgid "Send text to %s" msgstr "" @@ -32,52 +32,52 @@ msgstr "" msgid "Recent calls (%i)" msgstr "Contatando " -#: ../gtk/calllogs.c:312 +#: ../gtk/calllogs.c:314 msgid "n/a" msgstr "" -#: ../gtk/calllogs.c:315 +#: ../gtk/calllogs.c:317 #, fuzzy msgid "Aborted" msgstr "Abortado" -#: ../gtk/calllogs.c:318 +#: ../gtk/calllogs.c:320 #, fuzzy msgid "Missed" msgstr "Perdido" -#: ../gtk/calllogs.c:321 +#: ../gtk/calllogs.c:323 #, fuzzy msgid "Declined" msgstr "linha" -#: ../gtk/calllogs.c:327 +#: ../gtk/calllogs.c:329 #, c-format msgid "%i minute" msgid_plural "%i minutes" msgstr[0] "" msgstr[1] "" -#: ../gtk/calllogs.c:330 +#: ../gtk/calllogs.c:332 #, c-format msgid "%i second" msgid_plural "%i seconds" msgstr[0] "" msgstr[1] "" -#: ../gtk/calllogs.c:333 ../gtk/calllogs.c:339 +#: ../gtk/calllogs.c:335 ../gtk/calllogs.c:341 #, c-format msgid "%s\t%s" msgstr "" -#: ../gtk/calllogs.c:335 +#: ../gtk/calllogs.c:337 #, c-format msgid "" "%s\tQuality: %s\n" "%s\t%s\t" msgstr "" -#: ../gtk/calllogs.c:341 +#: ../gtk/calllogs.c:343 #, c-format msgid "" "%s\t\n" @@ -97,7 +97,7 @@ msgstr "" msgid "Couldn't find pixmap file: %s" msgstr "Não é possível achar arquivo pixmap: %s" -#: ../gtk/chat.c:363 ../gtk/friendlist.c:923 +#: ../gtk/chat.c:364 ../gtk/friendlist.c:924 msgid "Invalid sip contact !" msgstr "" @@ -145,7 +145,7 @@ msgstr "" msgid "Call with %s" msgstr "Bate-papo com %s" -#: ../gtk/main.c:1171 +#: ../gtk/main.c:1183 #, c-format msgid "" "%s would like to add you to his contact list.\n" @@ -154,76 +154,76 @@ msgid "" "If you answer no, this person will be temporarily blacklisted." msgstr "" -#: ../gtk/main.c:1248 +#: ../gtk/main.c:1260 #, c-format msgid "" "Please enter your password for username %s\n" " at realm %s:" msgstr "" -#: ../gtk/main.c:1364 +#: ../gtk/main.c:1376 #, fuzzy msgid "Call error" msgstr "Linphone - Histórico de chamadas" -#: ../gtk/main.c:1367 ../coreapi/linphonecore.c:3515 +#: ../gtk/main.c:1379 ../coreapi/linphonecore.c:3240 #, fuzzy msgid "Call ended" msgstr "Chamada cancelada." -#: ../gtk/main.c:1370 ../coreapi/linphonecore.c:254 +#: ../gtk/main.c:1382 msgid "Incoming call" msgstr "Camadas recebidas" -#: ../gtk/main.c:1372 ../gtk/incall_view.c:513 ../gtk/main.ui.h:5 +#: ../gtk/main.c:1384 ../gtk/incall_view.c:522 ../gtk/main.ui.h:5 msgid "Answer" msgstr "" -#: ../gtk/main.c:1374 ../gtk/main.ui.h:6 +#: ../gtk/main.c:1386 ../gtk/main.ui.h:6 #, fuzzy msgid "Decline" msgstr "linha" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy msgid "Call paused" msgstr "Abortado" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy, c-format msgid "by %s" msgstr "Contatando " -#: ../gtk/main.c:1447 +#: ../gtk/main.c:1459 #, c-format msgid "%s proposed to start video. Do you accept ?" msgstr "" -#: ../gtk/main.c:1609 +#: ../gtk/main.c:1621 msgid "Website link" msgstr "" -#: ../gtk/main.c:1658 +#: ../gtk/main.c:1670 msgid "Linphone - a video internet phone" msgstr "" -#: ../gtk/main.c:1750 +#: ../gtk/main.c:1762 #, c-format msgid "%s (Default)" msgstr "" -#: ../gtk/main.c:2086 ../coreapi/callbacks.c:927 +#: ../gtk/main.c:2099 ../coreapi/callbacks.c:949 #, c-format msgid "We are transferred to %s" msgstr "" -#: ../gtk/main.c:2096 +#: ../gtk/main.c:2109 msgid "" "No sound cards have been detected on this computer.\n" "You won't be able to send or receive audio calls." msgstr "" -#: ../gtk/main.c:2237 +#: ../gtk/main.c:2250 msgid "A free SIP video-phone" msgstr "" @@ -236,7 +236,7 @@ msgstr "Catálogo de endereços" msgid "Presence status" msgstr "Status de presença" -#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:550 ../gtk/contact.ui.h:1 +#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:552 ../gtk/contact.ui.h:1 msgid "Name" msgstr "Nome" @@ -255,142 +255,142 @@ msgstr "Sala de bate-papo" msgid "Search in %s directory" msgstr "" -#: ../gtk/friendlist.c:975 +#: ../gtk/friendlist.c:976 #, fuzzy, c-format msgid "Edit contact '%s'" msgstr "Edicar informação de contato" -#: ../gtk/friendlist.c:976 +#: ../gtk/friendlist.c:977 #, c-format msgid "Delete contact '%s'" msgstr "" -#: ../gtk/friendlist.c:977 +#: ../gtk/friendlist.c:978 #, c-format msgid "Delete chat history of '%s'" msgstr "" -#: ../gtk/friendlist.c:1028 +#: ../gtk/friendlist.c:1029 #, c-format msgid "Add new contact from %s directory" msgstr "" -#: ../gtk/propertybox.c:556 +#: ../gtk/propertybox.c:558 msgid "Rate (Hz)" msgstr "Taxa (Hz)" -#: ../gtk/propertybox.c:562 +#: ../gtk/propertybox.c:564 msgid "Status" msgstr "" -#: ../gtk/propertybox.c:568 +#: ../gtk/propertybox.c:570 #, fuzzy msgid "IP Bitrate (kbit/s)" msgstr "Bitrate mínimo (kbits/s)" -#: ../gtk/propertybox.c:575 +#: ../gtk/propertybox.c:577 msgid "Parameters" msgstr "Parâmetros" -#: ../gtk/propertybox.c:618 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:763 msgid "Enabled" msgstr "Ativado" -#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:622 ../gtk/propertybox.c:763 msgid "Disabled" msgstr "Desativado" -#: ../gtk/propertybox.c:807 +#: ../gtk/propertybox.c:809 #, fuzzy msgid "Account" msgstr "Aceitar" -#: ../gtk/propertybox.c:1061 +#: ../gtk/propertybox.c:1063 msgid "English" msgstr "" -#: ../gtk/propertybox.c:1062 +#: ../gtk/propertybox.c:1064 msgid "French" msgstr "" -#: ../gtk/propertybox.c:1063 +#: ../gtk/propertybox.c:1065 msgid "Swedish" msgstr "" -#: ../gtk/propertybox.c:1064 +#: ../gtk/propertybox.c:1066 msgid "Italian" msgstr "" -#: ../gtk/propertybox.c:1065 +#: ../gtk/propertybox.c:1067 msgid "Spanish" msgstr "" -#: ../gtk/propertybox.c:1066 +#: ../gtk/propertybox.c:1068 msgid "Brazilian Portugese" msgstr "" -#: ../gtk/propertybox.c:1067 +#: ../gtk/propertybox.c:1069 msgid "Polish" msgstr "" -#: ../gtk/propertybox.c:1068 +#: ../gtk/propertybox.c:1070 msgid "German" msgstr "" -#: ../gtk/propertybox.c:1069 +#: ../gtk/propertybox.c:1071 msgid "Russian" msgstr "" -#: ../gtk/propertybox.c:1070 +#: ../gtk/propertybox.c:1072 msgid "Japanese" msgstr "" -#: ../gtk/propertybox.c:1071 +#: ../gtk/propertybox.c:1073 msgid "Dutch" msgstr "" -#: ../gtk/propertybox.c:1072 +#: ../gtk/propertybox.c:1074 msgid "Hungarian" msgstr "" -#: ../gtk/propertybox.c:1073 +#: ../gtk/propertybox.c:1075 msgid "Czech" msgstr "" -#: ../gtk/propertybox.c:1074 +#: ../gtk/propertybox.c:1076 msgid "Chinese" msgstr "" -#: ../gtk/propertybox.c:1075 +#: ../gtk/propertybox.c:1077 msgid "Traditional Chinese" msgstr "" -#: ../gtk/propertybox.c:1076 +#: ../gtk/propertybox.c:1078 msgid "Norwegian" msgstr "" -#: ../gtk/propertybox.c:1077 +#: ../gtk/propertybox.c:1079 msgid "Hebrew" msgstr "" -#: ../gtk/propertybox.c:1078 +#: ../gtk/propertybox.c:1080 msgid "Serbian" msgstr "" -#: ../gtk/propertybox.c:1145 +#: ../gtk/propertybox.c:1147 msgid "" "You need to restart linphone for the new language selection to take effect." msgstr "" -#: ../gtk/propertybox.c:1223 +#: ../gtk/propertybox.c:1225 msgid "None" msgstr "Nenhum" -#: ../gtk/propertybox.c:1227 +#: ../gtk/propertybox.c:1229 msgid "SRTP" msgstr "" -#: ../gtk/propertybox.c:1233 +#: ../gtk/propertybox.c:1235 msgid "ZRTP" msgstr "" @@ -460,110 +460,114 @@ msgstr "" msgid "Enter your linphone.org username" msgstr "" -#: ../gtk/setupwizard.c:96 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 +#: ../gtk/setupwizard.c:102 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 #, fuzzy msgid "Username:" msgstr "Usuário" -#: ../gtk/setupwizard.c:98 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 +#: ../gtk/setupwizard.c:104 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 #, fuzzy msgid "Password:" msgstr "Senha:" -#: ../gtk/setupwizard.c:118 +#: ../gtk/setupwizard.c:124 msgid "Enter your account informations" msgstr "" -#: ../gtk/setupwizard.c:125 +#: ../gtk/setupwizard.c:140 #, fuzzy msgid "Username*" msgstr "Usuário" -#: ../gtk/setupwizard.c:126 +#: ../gtk/setupwizard.c:141 #, fuzzy msgid "Password*" msgstr "Senha:" -#: ../gtk/setupwizard.c:129 +#: ../gtk/setupwizard.c:144 msgid "Domain*" msgstr "" -#: ../gtk/setupwizard.c:130 +#: ../gtk/setupwizard.c:145 msgid "Proxy" msgstr "" -#: ../gtk/setupwizard.c:302 +#: ../gtk/setupwizard.c:317 msgid "(*) Required fields" msgstr "" -#: ../gtk/setupwizard.c:303 +#: ../gtk/setupwizard.c:318 #, fuzzy msgid "Username: (*)" msgstr "Usuário" -#: ../gtk/setupwizard.c:305 +#: ../gtk/setupwizard.c:320 #, fuzzy msgid "Password: (*)" msgstr "Senha:" -#: ../gtk/setupwizard.c:307 +#: ../gtk/setupwizard.c:322 msgid "Email: (*)" msgstr "" -#: ../gtk/setupwizard.c:309 +#: ../gtk/setupwizard.c:324 msgid "Confirm your password: (*)" msgstr "" -#: ../gtk/setupwizard.c:373 +#: ../gtk/setupwizard.c:338 +msgid "Keep me informed with linphone updates" +msgstr "" + +#: ../gtk/setupwizard.c:394 msgid "" "Error, account not validated, username already used or server unreachable.\n" "Please go back and try again." msgstr "" -#: ../gtk/setupwizard.c:384 +#: ../gtk/setupwizard.c:405 msgid "Thank you. Your account is now configured and ready for use." msgstr "" -#: ../gtk/setupwizard.c:392 +#: ../gtk/setupwizard.c:413 msgid "" "Please validate your account by clicking on the link we just sent you by " "email.\n" "Then come back here and press Next button." msgstr "" -#: ../gtk/setupwizard.c:564 +#: ../gtk/setupwizard.c:600 msgid "SIP account configuration assistant" msgstr "" -#: ../gtk/setupwizard.c:582 +#: ../gtk/setupwizard.c:618 msgid "Welcome to the account setup assistant" msgstr "" -#: ../gtk/setupwizard.c:587 +#: ../gtk/setupwizard.c:623 msgid "Account setup assistant" msgstr "" -#: ../gtk/setupwizard.c:593 +#: ../gtk/setupwizard.c:629 msgid "Configure your account (step 1/1)" msgstr "" -#: ../gtk/setupwizard.c:598 +#: ../gtk/setupwizard.c:634 msgid "Enter your sip username (step 1/1)" msgstr "" -#: ../gtk/setupwizard.c:602 +#: ../gtk/setupwizard.c:638 msgid "Enter account information (step 1/2)" msgstr "" -#: ../gtk/setupwizard.c:611 +#: ../gtk/setupwizard.c:647 msgid "Validation (step 2/2)" msgstr "" -#: ../gtk/setupwizard.c:616 +#: ../gtk/setupwizard.c:652 msgid "Error" msgstr "" -#: ../gtk/setupwizard.c:620 ../gtk/audio_assistant.c:519 +#: ../gtk/setupwizard.c:656 ../gtk/audio_assistant.c:527 msgid "Terminating" msgstr "" @@ -633,135 +637,135 @@ msgstr "Histórico de chamadas" msgid "Direct or through server" msgstr "" -#: ../gtk/incall_view.c:266 ../gtk/incall_view.c:276 +#: ../gtk/incall_view.c:267 ../gtk/incall_view.c:279 #, c-format msgid "" "download: %f\n" "upload: %f (kbit/s)" msgstr "" -#: ../gtk/incall_view.c:271 ../gtk/incall_view.c:272 +#: ../gtk/incall_view.c:272 ../gtk/incall_view.c:274 #, c-format -msgid "%ix%i" +msgid "%ix%i @ %f fps" msgstr "" -#: ../gtk/incall_view.c:301 +#: ../gtk/incall_view.c:304 #, c-format msgid "%.3f seconds" msgstr "" -#: ../gtk/incall_view.c:399 ../gtk/main.ui.h:12 +#: ../gtk/incall_view.c:407 ../gtk/main.ui.h:12 msgid "Hang up" msgstr "" -#: ../gtk/incall_view.c:492 +#: ../gtk/incall_view.c:501 #, fuzzy msgid "Calling..." msgstr "Contatando " -#: ../gtk/incall_view.c:495 ../gtk/incall_view.c:698 +#: ../gtk/incall_view.c:504 ../gtk/incall_view.c:707 msgid "00::00::00" msgstr "" -#: ../gtk/incall_view.c:506 +#: ../gtk/incall_view.c:515 #, fuzzy msgid "Incoming call" msgstr "Camadas recebidas" -#: ../gtk/incall_view.c:543 +#: ../gtk/incall_view.c:552 msgid "good" msgstr "" -#: ../gtk/incall_view.c:545 +#: ../gtk/incall_view.c:554 msgid "average" msgstr "" -#: ../gtk/incall_view.c:547 +#: ../gtk/incall_view.c:556 msgid "poor" msgstr "" -#: ../gtk/incall_view.c:549 +#: ../gtk/incall_view.c:558 msgid "very poor" msgstr "" -#: ../gtk/incall_view.c:551 +#: ../gtk/incall_view.c:560 msgid "too bad" msgstr "" -#: ../gtk/incall_view.c:552 ../gtk/incall_view.c:568 +#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:577 msgid "unavailable" msgstr "" -#: ../gtk/incall_view.c:660 +#: ../gtk/incall_view.c:669 msgid "Secured by SRTP" msgstr "" -#: ../gtk/incall_view.c:666 +#: ../gtk/incall_view.c:675 #, c-format msgid "Secured by ZRTP - [auth token: %s]" msgstr "" -#: ../gtk/incall_view.c:672 +#: ../gtk/incall_view.c:681 msgid "Set unverified" msgstr "" -#: ../gtk/incall_view.c:672 ../gtk/main.ui.h:4 +#: ../gtk/incall_view.c:681 ../gtk/main.ui.h:4 msgid "Set verified" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In conference" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 #, fuzzy msgid "In call" msgstr "Contatando " -#: ../gtk/incall_view.c:729 +#: ../gtk/incall_view.c:738 #, fuzzy msgid "Paused call" msgstr "Contatando " -#: ../gtk/incall_view.c:742 +#: ../gtk/incall_view.c:751 #, c-format msgid "%02i::%02i::%02i" msgstr "" -#: ../gtk/incall_view.c:760 +#: ../gtk/incall_view.c:772 #, fuzzy msgid "Call ended." msgstr "Chamada cancelada." -#: ../gtk/incall_view.c:791 +#: ../gtk/incall_view.c:803 msgid "Transfer in progress" msgstr "" -#: ../gtk/incall_view.c:794 +#: ../gtk/incall_view.c:806 msgid "Transfer done." msgstr "" -#: ../gtk/incall_view.c:797 +#: ../gtk/incall_view.c:809 #, fuzzy msgid "Transfer failed." msgstr "Histórico de chamadas" -#: ../gtk/incall_view.c:841 +#: ../gtk/incall_view.c:853 msgid "Resume" msgstr "" -#: ../gtk/incall_view.c:848 ../gtk/main.ui.h:9 +#: ../gtk/incall_view.c:860 ../gtk/main.ui.h:9 msgid "Pause" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, c-format msgid "" "Recording into\n" "%s %s" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 msgid "(Paused)" msgstr "" @@ -796,64 +800,64 @@ msgstr "" msgid "Too loud" msgstr "" -#: ../gtk/audio_assistant.c:316 +#: ../gtk/audio_assistant.c:318 msgid "" "Welcome !\n" "This assistant will help you to configure audio settings for Linphone" msgstr "" -#: ../gtk/audio_assistant.c:326 +#: ../gtk/audio_assistant.c:328 #, fuzzy msgid "Capture device" msgstr "Dispositivo de captura de som:" -#: ../gtk/audio_assistant.c:327 +#: ../gtk/audio_assistant.c:329 #, fuzzy msgid "Recorded volume" msgstr "Origem de gravação:" -#: ../gtk/audio_assistant.c:331 +#: ../gtk/audio_assistant.c:333 msgid "No voice" msgstr "" -#: ../gtk/audio_assistant.c:367 +#: ../gtk/audio_assistant.c:369 #, fuzzy msgid "Playback device" msgstr "Dispositivo de som:" -#: ../gtk/audio_assistant.c:368 +#: ../gtk/audio_assistant.c:370 msgid "Play three beeps" msgstr "" -#: ../gtk/audio_assistant.c:400 +#: ../gtk/audio_assistant.c:403 msgid "Press the record button and say some words" msgstr "" -#: ../gtk/audio_assistant.c:401 +#: ../gtk/audio_assistant.c:404 msgid "Listen to your record voice" msgstr "" -#: ../gtk/audio_assistant.c:430 +#: ../gtk/audio_assistant.c:433 msgid "Let's start Linphone now" msgstr "" -#: ../gtk/audio_assistant.c:488 +#: ../gtk/audio_assistant.c:496 msgid "Audio Assistant" msgstr "" -#: ../gtk/audio_assistant.c:498 ../gtk/main.ui.h:31 +#: ../gtk/audio_assistant.c:506 ../gtk/main.ui.h:31 msgid "Audio assistant" msgstr "" -#: ../gtk/audio_assistant.c:503 +#: ../gtk/audio_assistant.c:511 msgid "Mic Gain calibration" msgstr "" -#: ../gtk/audio_assistant.c:509 +#: ../gtk/audio_assistant.c:517 msgid "Speaker volume calibration" msgstr "" -#: ../gtk/audio_assistant.c:514 +#: ../gtk/audio_assistant.c:522 msgid "Record and Play" msgstr "" @@ -1839,100 +1843,70 @@ msgstr "Contatando " msgid "Please wait while fetching configuration from server..." msgstr "" -#: ../coreapi/linphonecore.c:242 -msgid "aborted" -msgstr "Abortado" - -#: ../coreapi/linphonecore.c:245 -msgid "completed" -msgstr "Competado" - -#: ../coreapi/linphonecore.c:248 -msgid "missed" -msgstr "Perdido" - -#: ../coreapi/linphonecore.c:253 -#, fuzzy, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" -"%s em %sDe: %s\n" -"Para: %s\n" -"Status: %s\n" -"Duração: %i min %i seg\n" - -#: ../coreapi/linphonecore.c:254 -msgid "Outgoing call" -msgstr "Chamadas efetuadas" - -#: ../coreapi/linphonecore.c:1287 +#: ../coreapi/linphonecore.c:1034 #, fuzzy msgid "Ready" msgstr "Pronto." -#: ../coreapi/linphonecore.c:2248 +#: ../coreapi/linphonecore.c:1967 #, fuzzy msgid "Configuring" msgstr "Informações" -#: ../coreapi/linphonecore.c:2410 +#: ../coreapi/linphonecore.c:2133 msgid "Looking for telephone number destination..." msgstr "Procurando por telefone de destino..." -#: ../coreapi/linphonecore.c:2413 +#: ../coreapi/linphonecore.c:2136 msgid "Could not resolve this number." msgstr "Não foi possível encontrar este número." #. must be known at that time -#: ../coreapi/linphonecore.c:2695 +#: ../coreapi/linphonecore.c:2418 #, fuzzy msgid "Contacting" msgstr "Contatando " -#: ../coreapi/linphonecore.c:2702 +#: ../coreapi/linphonecore.c:2425 #, fuzzy msgid "Could not call" msgstr "Não é possível achar arquivo pixmap: %s" -#: ../coreapi/linphonecore.c:2852 +#: ../coreapi/linphonecore.c:2576 msgid "Sorry, we have reached the maximum number of simultaneous calls" msgstr "" -#: ../coreapi/linphonecore.c:3022 +#: ../coreapi/linphonecore.c:2745 #, fuzzy msgid "is contacting you" msgstr "está chamado você." -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid " and asked autoanswer." msgstr "" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid "." msgstr "" -#: ../coreapi/linphonecore.c:3139 +#: ../coreapi/linphonecore.c:2865 msgid "Modifying call parameters..." msgstr "" -#: ../coreapi/linphonecore.c:3469 +#: ../coreapi/linphonecore.c:3194 msgid "Connected." msgstr "Conectado." -#: ../coreapi/linphonecore.c:3495 +#: ../coreapi/linphonecore.c:3220 #, fuzzy msgid "Call aborted" msgstr "Abortado" -#: ../coreapi/linphonecore.c:3685 +#: ../coreapi/linphonecore.c:3412 msgid "Could not pause the call" msgstr "" -#: ../coreapi/linphonecore.c:3690 +#: ../coreapi/linphonecore.c:3417 msgid "Pausing the current call..." msgstr "" @@ -1999,149 +1973,174 @@ msgstr "Informações" msgid "Unknown-bug" msgstr "" -#: ../coreapi/proxy.c:279 +#: ../coreapi/proxy.c:314 msgid "" "The sip proxy address you entered is invalid, it must start with \"sip:\" " "followed by a hostname." msgstr "" -#: ../coreapi/proxy.c:285 +#: ../coreapi/proxy.c:320 msgid "" "The sip identity you entered is invalid.\n" "It should look like sip:username@proxydomain, such as sip:alice@example.net" msgstr "" -#: ../coreapi/proxy.c:1299 +#: ../coreapi/proxy.c:1369 #, fuzzy, c-format msgid "Could not login as %s" msgstr "Não é possível achar arquivo pixmap: %s" -#: ../coreapi/callbacks.c:354 +#: ../coreapi/callbacks.c:355 #, fuzzy msgid "Remote ringing." msgstr "Serviços remotos" -#: ../coreapi/callbacks.c:370 +#: ../coreapi/callbacks.c:373 #, fuzzy msgid "Remote ringing..." msgstr "Serviços remotos" -#: ../coreapi/callbacks.c:381 +#: ../coreapi/callbacks.c:384 msgid "Early media." msgstr "" -#: ../coreapi/callbacks.c:432 +#: ../coreapi/callbacks.c:435 #, fuzzy, c-format msgid "Call with %s is paused." msgstr "Bate-papo com %s" -#: ../coreapi/callbacks.c:445 +#: ../coreapi/callbacks.c:448 #, c-format msgid "Call answered by %s - on hold." msgstr "" -#: ../coreapi/callbacks.c:456 +#: ../coreapi/callbacks.c:459 #, fuzzy msgid "Call resumed." msgstr "Chamada cancelada." -#: ../coreapi/callbacks.c:461 +#: ../coreapi/callbacks.c:464 #, fuzzy, c-format msgid "Call answered by %s." msgstr "" "Ligar ou\n" "atender" -#: ../coreapi/callbacks.c:480 +#: ../coreapi/callbacks.c:483 msgid "Incompatible, check codecs or security settings..." msgstr "" -#: ../coreapi/callbacks.c:531 +#: ../coreapi/callbacks.c:512 msgid "We have been resumed." msgstr "" -#: ../coreapi/callbacks.c:541 +#: ../coreapi/callbacks.c:521 msgid "We are paused by other party." msgstr "" -#: ../coreapi/callbacks.c:558 +#: ../coreapi/callbacks.c:556 msgid "Call is updated by remote." msgstr "" -#: ../coreapi/callbacks.c:637 +#: ../coreapi/callbacks.c:658 msgid "Call terminated." msgstr "" -#: ../coreapi/callbacks.c:666 +#: ../coreapi/callbacks.c:687 msgid "User is busy." msgstr "Usuário está ocupado." -#: ../coreapi/callbacks.c:667 +#: ../coreapi/callbacks.c:688 msgid "User is temporarily unavailable." msgstr "Usuário está temporáriamente indisponível." #. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:669 +#: ../coreapi/callbacks.c:690 msgid "User does not want to be disturbed." msgstr "" -#: ../coreapi/callbacks.c:670 +#: ../coreapi/callbacks.c:691 msgid "Call declined." msgstr "" -#: ../coreapi/callbacks.c:685 +#: ../coreapi/callbacks.c:706 msgid "Request timeout." msgstr "" -#: ../coreapi/callbacks.c:716 +#: ../coreapi/callbacks.c:737 #, fuzzy msgid "Redirected" msgstr "Redirecionado para %s..." -#: ../coreapi/callbacks.c:766 +#: ../coreapi/callbacks.c:787 msgid "Incompatible media parameters." msgstr "" -#: ../coreapi/callbacks.c:777 +#: ../coreapi/callbacks.c:798 #, fuzzy msgid "Call failed." msgstr "Histórico de chamadas" -#: ../coreapi/callbacks.c:852 +#: ../coreapi/callbacks.c:878 #, fuzzy, c-format msgid "Registration on %s successful." msgstr "Registro em %s efetuado." -#: ../coreapi/callbacks.c:853 +#: ../coreapi/callbacks.c:879 #, fuzzy, c-format msgid "Unregistration on %s done." msgstr "Registro em %s efetuado." -#: ../coreapi/callbacks.c:875 +#: ../coreapi/callbacks.c:897 msgid "no response timeout" msgstr "" -#: ../coreapi/callbacks.c:878 +#: ../coreapi/callbacks.c:900 #, fuzzy, c-format msgid "Registration on %s failed: %s" msgstr "Registro falhou (tempo esgotado)." -#: ../coreapi/callbacks.c:885 +#: ../coreapi/callbacks.c:907 msgid "Service unavailable, retrying" msgstr "" -#: ../coreapi/linphonecall.c:175 +#: ../coreapi/linphonecall.c:177 #, fuzzy, c-format msgid "Authentication token is %s" msgstr "Informações de autenticação" -#: ../coreapi/linphonecall.c:2994 +#: ../coreapi/linphonecall.c:2932 #, fuzzy, c-format msgid "You have missed %i call." msgid_plural "You have missed %i calls." msgstr[0] "Você perdeu %i ligação(ões)." msgstr[1] "Você perdeu %i ligação(ões)." +#~ msgid "aborted" +#~ msgstr "Abortado" + +#~ msgid "completed" +#~ msgstr "Competado" + +#~ msgid "missed" +#~ msgstr "Perdido" + +#, fuzzy +#~ msgid "" +#~ "%s at %s\n" +#~ "From: %s\n" +#~ "To: %s\n" +#~ "Status: %s\n" +#~ "Duration: %i mn %i sec\n" +#~ msgstr "" +#~ "%s em %sDe: %s\n" +#~ "Para: %s\n" +#~ "Status: %s\n" +#~ "Duração: %i min %i seg\n" + +#~ msgid "Outgoing call" +#~ msgstr "Chamadas efetuadas" + #~ msgid "Chat with %s" #~ msgstr "Bate-papo com %s" diff --git a/po/ru.po b/po/ru.po index d2a440a31..6e916a63c 100644 --- a/po/ru.po +++ b/po/ru.po @@ -1,57 +1,56 @@ # SIP Telephony Application. -# Copyright (C) 2001, 2002 Free Software Foundation, Inc. +# Copyright (C) 2001-2014 Free Software Foundation, Inc. # Simon Morlat , 2001. +# Maxim Prokopyev , 2010. +# Alexey Loginov , 2014. # msgid "" msgstr "" -"Project-Id-Version: linphone 0.7.1\n" +"Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-01 21:24+0200\n" -"PO-Revision-Date: 2010-01-22 18:43+0300\n" -"Last-Translator: Maxim Prokopyev \n" -"Language-Team: Russian \n" +"POT-Creation-Date: 2014-09-15 09:24+0200\n" +"PO-Revision-Date: 2014-09-10 01:32+0300\n" +"Last-Translator: AlexL \n" +"Language-Team: Russian \n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" -"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:973 +#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:974 #, c-format msgid "Call %s" -msgstr "Набрать %s" +msgstr "Звонок %s" -#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:974 +#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:975 #, c-format msgid "Send text to %s" -msgstr "Послать текст к %s" +msgstr "Послать текст для %s" #: ../gtk/calllogs.c:232 -#, fuzzy, c-format +#, c-format msgid "Recent calls (%i)" -msgstr "Соединен с" +msgstr "Последние вызовы (%i)" -#: ../gtk/calllogs.c:312 +#: ../gtk/calllogs.c:314 msgid "n/a" -msgstr "н/д" +msgstr "—" -#: ../gtk/calllogs.c:315 -#, fuzzy +#: ../gtk/calllogs.c:317 msgid "Aborted" -msgstr "отмененный" +msgstr "Прервано" -#: ../gtk/calllogs.c:318 -#, fuzzy +#: ../gtk/calllogs.c:320 msgid "Missed" -msgstr "пропущенный" +msgstr "Пропущено" -#: ../gtk/calllogs.c:321 -#, fuzzy +#: ../gtk/calllogs.c:323 msgid "Declined" -msgstr "Отклонить" +msgstr "Отклонено" -#: ../gtk/calllogs.c:327 +#: ../gtk/calllogs.c:329 #, c-format msgid "%i minute" msgid_plural "%i minutes" @@ -59,7 +58,7 @@ msgstr[0] "%i минута" msgstr[1] "%i минуты" msgstr[2] "%i минут" -#: ../gtk/calllogs.c:330 +#: ../gtk/calllogs.c:332 #, c-format msgid "%i second" msgid_plural "%i seconds" @@ -67,30 +66,28 @@ msgstr[0] "%i секунда" msgstr[1] "%i секунды" msgstr[2] "%i секунд" -#: ../gtk/calllogs.c:333 ../gtk/calllogs.c:339 -#, fuzzy, c-format +#: ../gtk/calllogs.c:335 ../gtk/calllogs.c:341 +#, c-format msgid "%s\t%s" -msgstr "" -"%s\t%s\tКачество: %s\n" -"%s\t%s %s\t" +msgstr "%s\t%s" -#: ../gtk/calllogs.c:335 -#, fuzzy, c-format +#: ../gtk/calllogs.c:337 +#, c-format msgid "" "%s\tQuality: %s\n" "%s\t%s\t" msgstr "" -"%s\t%s\tКачество: %s\n" -"%s\t%s %s\t" +"%s\tКачество: %s\n" +"%s\t%s\t" -#: ../gtk/calllogs.c:341 -#, fuzzy, c-format +#: ../gtk/calllogs.c:343 +#, c-format msgid "" "%s\t\n" "%s" msgstr "" -"%s\t%s\tКачество: %s\n" -"%s\t%s %s\t" +"%s\t\n" +"%s" #: ../gtk/conference.c:38 ../gtk/main.ui.h:13 msgid "Conference" @@ -98,67 +95,65 @@ msgstr "Конференция" #: ../gtk/conference.c:46 msgid "Me" -msgstr "Я" +msgstr "Мне" #: ../gtk/support.c:49 ../gtk/support.c:73 ../gtk/support.c:102 #, c-format msgid "Couldn't find pixmap file: %s" msgstr "Невозможно найти графический файл: %s" -#: ../gtk/chat.c:363 ../gtk/friendlist.c:923 +#: ../gtk/chat.c:364 ../gtk/friendlist.c:924 msgid "Invalid sip contact !" -msgstr "Неверный sip-контакт!" +msgstr "Неверный sip контакт!" #: ../gtk/main.c:107 msgid "log to stdout some debug information while running." msgstr "" "Вывод некоторой отладочной информации на устройство стандартного вывода во " -"время работы" +"время работы." #: ../gtk/main.c:114 msgid "path to a file to write logs into." -msgstr "путь к файлу для записи журнала работы." +msgstr "Путь к файлу для записи логов." #: ../gtk/main.c:121 msgid "Start linphone with video disabled." -msgstr "" +msgstr "Запуск linphone с видео отключен." #: ../gtk/main.c:128 msgid "Start only in the system tray, do not show the main interface." -msgstr "Запускать только в системном лотке, не показывая главное окно" +msgstr "Показывать только в системном лотке, не запуская главное окно." #: ../gtk/main.c:135 msgid "address to call right now" -msgstr "адрес для звонка" +msgstr "Адрес для звонка прямо сейчас." #: ../gtk/main.c:142 msgid "if set automatically answer incoming calls" -msgstr "автоматически принимать входящие вызовы, если включено" +msgstr "Если установлено, то автоматический приём входящих звонков." #: ../gtk/main.c:149 msgid "" "Specifiy a working directory (should be the base of the installation, eg: c:" "\\Program Files\\Linphone)" msgstr "" -"Укажите рабочий каталог (должен содержать установленные файлы приложения, " -"например: c:\\Program Files\\Linphone)" +"Определить рабочий каталог (относительно каталога установки, например: c:" +"\\Program Files\\Linphone)" #: ../gtk/main.c:156 -#, fuzzy msgid "Configuration file" -msgstr "Подтверждение" +msgstr "Файл конфигурации" #: ../gtk/main.c:163 -#, fuzzy msgid "Run the audio assistant" -msgstr "Помощник настройки учётной записи" +msgstr "Запустить помощника аудио" #: ../gtk/main.c:590 #, c-format msgid "Call with %s" -msgstr "Чат с %s" +msgstr "Звонок с %s" -#: ../gtk/main.c:1171 +#: ../gtk/main.c:1183 #, c-format msgid "" "%s would like to add you to his contact list.\n" @@ -166,81 +161,81 @@ msgid "" "list ?\n" "If you answer no, this person will be temporarily blacklisted." msgstr "" -"%s хочет добавить вас в свой контакт-лист.\n" -"Вы разрешаете ему(ей) видеть статус вашего присутствия или хотите добавить " -"его(её) в свой контактный лист?\n" -"Если вы ответите Нет, этот человек будет временно заблокирован." +"%s вы бы хотели быть добавленным в этот контактный лист.\n" +"Вы разрешаете ему(ей) видеть ваш статус присутствия или добавить в " +"контактный лист?\n" +"Если вы ответите Нет, эта персона будет временно в чёрном списке." -#: ../gtk/main.c:1248 -#, fuzzy, c-format +#: ../gtk/main.c:1260 +#, c-format msgid "" "Please enter your password for username %s\n" " at realm %s:" msgstr "" "Пожалуйста, введите пароль для пользователя %s\n" -" в домене %s:" +" для реалм (рилм) %s:" -#: ../gtk/main.c:1364 +#: ../gtk/main.c:1376 msgid "Call error" -msgstr "Ошибка вызова" +msgstr "Ошибка звонка" -#: ../gtk/main.c:1367 ../coreapi/linphonecore.c:3515 +#: ../gtk/main.c:1379 ../coreapi/linphonecore.c:3240 msgid "Call ended" -msgstr "Разговор окончен" +msgstr "Звонок окончен" -#: ../gtk/main.c:1370 ../coreapi/linphonecore.c:254 +#: ../gtk/main.c:1382 msgid "Incoming call" -msgstr "Входящий вызов" +msgstr "Входящий звонок" -#: ../gtk/main.c:1372 ../gtk/incall_view.c:513 ../gtk/main.ui.h:5 +#: ../gtk/main.c:1384 ../gtk/incall_view.c:522 ../gtk/main.ui.h:5 msgid "Answer" -msgstr "Ответить" +msgstr "Ответ" -#: ../gtk/main.c:1374 ../gtk/main.ui.h:6 +#: ../gtk/main.c:1386 ../gtk/main.ui.h:6 msgid "Decline" msgstr "Отклонить" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 msgid "Call paused" -msgstr "Вызов приостановлен" +msgstr "Звонок приостановлен" -#: ../gtk/main.c:1380 -#, fuzzy, c-format +#: ../gtk/main.c:1392 +#, c-format msgid "by %s" -msgstr "Порты" +msgstr "%s" -#: ../gtk/main.c:1447 +#: ../gtk/main.c:1459 #, c-format msgid "%s proposed to start video. Do you accept ?" -msgstr "" +msgstr "%s предложил запустить видео. Вы принимаете?" -#: ../gtk/main.c:1609 +#: ../gtk/main.c:1621 msgid "Website link" -msgstr "Ссылка на сайт" +msgstr "Домашняя страница" -#: ../gtk/main.c:1658 +#: ../gtk/main.c:1670 msgid "Linphone - a video internet phone" -msgstr "Linphone - видео-телефон для интернета" +msgstr "Linphone - интернет видео телефон" -#: ../gtk/main.c:1750 +#: ../gtk/main.c:1762 #, c-format msgid "%s (Default)" -msgstr "%s (По умолчанию)" +msgstr "%s (по умолчанию)" -#: ../gtk/main.c:2086 ../coreapi/callbacks.c:927 +#: ../gtk/main.c:2099 ../coreapi/callbacks.c:949 #, c-format msgid "We are transferred to %s" -msgstr "Мы переведены на %s" +msgstr "Мы передали в %s" -#: ../gtk/main.c:2096 +#: ../gtk/main.c:2109 msgid "" "No sound cards have been detected on this computer.\n" "You won't be able to send or receive audio calls." msgstr "" -"На этом компьютере не обнаружено ни одной звуковой карты.\n" -"Вы не сможете совершать или принимать аудио-вызовы." +"Звуковые карты не были обнаружены на этом компьютере.\n" +"Вы не сможете отправлять или получать аудио звонки." -#: ../gtk/main.c:2237 +#: ../gtk/main.c:2250 msgid "A free SIP video-phone" msgstr "Свободный SIP видео-телефон" @@ -252,161 +247,159 @@ msgstr "Добавить в адресную книгу" msgid "Presence status" msgstr "Статус присутствия" -#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:550 ../gtk/contact.ui.h:1 +#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:552 ../gtk/contact.ui.h:1 msgid "Name" msgstr "Имя" #: ../gtk/friendlist.c:721 msgid "Call" -msgstr "Вызов" +msgstr "Звонок" #: ../gtk/friendlist.c:726 -#, fuzzy msgid "Chat" -msgstr "Комната чата" +msgstr "Чат" #: ../gtk/friendlist.c:756 #, c-format msgid "Search in %s directory" msgstr "Поиск в директории %s" -#: ../gtk/friendlist.c:975 +#: ../gtk/friendlist.c:976 #, c-format msgid "Edit contact '%s'" msgstr "Редактировать контакт '%s'" -#: ../gtk/friendlist.c:976 +#: ../gtk/friendlist.c:977 #, c-format msgid "Delete contact '%s'" msgstr "Удалить контакт '%s'" -#: ../gtk/friendlist.c:977 -#, fuzzy, c-format +#: ../gtk/friendlist.c:978 +#, c-format msgid "Delete chat history of '%s'" -msgstr "Удалить контакт '%s'" +msgstr "Удалить историю чата для '%s'" -#: ../gtk/friendlist.c:1028 +#: ../gtk/friendlist.c:1029 #, c-format msgid "Add new contact from %s directory" msgstr "Добавить новый контакт из директории '%s'" -#: ../gtk/propertybox.c:556 +#: ../gtk/propertybox.c:558 msgid "Rate (Hz)" msgstr "Частота (Гц)" -#: ../gtk/propertybox.c:562 +#: ../gtk/propertybox.c:564 msgid "Status" msgstr "Статус" -#: ../gtk/propertybox.c:568 -#, fuzzy +#: ../gtk/propertybox.c:570 msgid "IP Bitrate (kbit/s)" -msgstr "Минимальный битрейт (кбит/с)" +msgstr "IP битрейт (КБит/сек)" -#: ../gtk/propertybox.c:575 +#: ../gtk/propertybox.c:577 msgid "Parameters" msgstr "Параметры" -#: ../gtk/propertybox.c:618 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:763 msgid "Enabled" -msgstr "Включен" +msgstr "Разрешён" -#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:622 ../gtk/propertybox.c:763 msgid "Disabled" -msgstr "Отключен" +msgstr "Не разрешён" -#: ../gtk/propertybox.c:807 +#: ../gtk/propertybox.c:809 msgid "Account" -msgstr "Учетная запись" +msgstr "Учётная запись" -#: ../gtk/propertybox.c:1061 +#: ../gtk/propertybox.c:1063 msgid "English" msgstr "Английский" -#: ../gtk/propertybox.c:1062 +#: ../gtk/propertybox.c:1064 msgid "French" msgstr "Французский" -#: ../gtk/propertybox.c:1063 +#: ../gtk/propertybox.c:1065 msgid "Swedish" msgstr "Шведский" -#: ../gtk/propertybox.c:1064 +#: ../gtk/propertybox.c:1066 msgid "Italian" msgstr "Итальянский" -#: ../gtk/propertybox.c:1065 +#: ../gtk/propertybox.c:1067 msgid "Spanish" msgstr "Испанский" -#: ../gtk/propertybox.c:1066 +#: ../gtk/propertybox.c:1068 msgid "Brazilian Portugese" msgstr "Бразильский португальский" -#: ../gtk/propertybox.c:1067 +#: ../gtk/propertybox.c:1069 msgid "Polish" msgstr "Польский" -#: ../gtk/propertybox.c:1068 +#: ../gtk/propertybox.c:1070 msgid "German" msgstr "Немецкий" -#: ../gtk/propertybox.c:1069 +#: ../gtk/propertybox.c:1071 msgid "Russian" msgstr "Русский" -#: ../gtk/propertybox.c:1070 +#: ../gtk/propertybox.c:1072 msgid "Japanese" msgstr "Японский" -#: ../gtk/propertybox.c:1071 +#: ../gtk/propertybox.c:1073 msgid "Dutch" -msgstr "Нидерландский" +msgstr "Датский" -#: ../gtk/propertybox.c:1072 +#: ../gtk/propertybox.c:1074 msgid "Hungarian" msgstr "Венгерский" -#: ../gtk/propertybox.c:1073 +#: ../gtk/propertybox.c:1075 msgid "Czech" msgstr "Чешский" -#: ../gtk/propertybox.c:1074 +#: ../gtk/propertybox.c:1076 msgid "Chinese" msgstr "Китайский" -#: ../gtk/propertybox.c:1075 +#: ../gtk/propertybox.c:1077 msgid "Traditional Chinese" msgstr "Традиционный китайский" -#: ../gtk/propertybox.c:1076 +#: ../gtk/propertybox.c:1078 msgid "Norwegian" msgstr "Норвежский" -#: ../gtk/propertybox.c:1077 +#: ../gtk/propertybox.c:1079 msgid "Hebrew" -msgstr "" +msgstr "Иврит" -#: ../gtk/propertybox.c:1078 +#: ../gtk/propertybox.c:1080 msgid "Serbian" -msgstr "" +msgstr "Сербский" -#: ../gtk/propertybox.c:1145 +#: ../gtk/propertybox.c:1147 msgid "" "You need to restart linphone for the new language selection to take effect." msgstr "" -"Вы должны перезапустить Linphone для того, чтобы языковые настройки вступили " +"Вы должны перезагрузить linphone для того, чтобы языковые настройки вступили " "в силу." -#: ../gtk/propertybox.c:1223 +#: ../gtk/propertybox.c:1225 msgid "None" msgstr "Нет" -#: ../gtk/propertybox.c:1227 +#: ../gtk/propertybox.c:1229 msgid "SRTP" msgstr "SRTP" -#: ../gtk/propertybox.c:1233 +#: ../gtk/propertybox.c:1235 msgid "ZRTP" msgstr "ZRTP" @@ -416,12 +409,12 @@ msgid "" "A more recent version is availalble from %s.\n" "Would you like to open a browser to download it ?" msgstr "" -"Доступна более новая версия с %s\n" +"Доступна новая версия с %s.\n" "Открыть браузер для загрузки?" #: ../gtk/update.c:91 msgid "You are running the lastest version." -msgstr "Вы используете самую последнюю версию." +msgstr "Вы работаете с последней версией." #: ../gtk/buddylookup.c:85 msgid "Firstname, Lastname" @@ -466,454 +459,446 @@ msgstr "Создать учётную запись на linphone.org" #: ../gtk/setupwizard.c:44 msgid "I have already a linphone.org account and I just want to use it" msgstr "" -"У меня уже есть учётная запись на linphone.org и я хочу использовать её" +"Я уже имею учётную запись на linphone.org и только хочу использовать её" #: ../gtk/setupwizard.c:45 msgid "I have already a sip account and I just want to use it" -msgstr "У меня уже есть учётная запись SIP и я хочу использовать её" +msgstr "Я уже имею учётную запись sip и только хочу использовать её" #: ../gtk/setupwizard.c:46 msgid "I want to specify a remote configuration URI" -msgstr "" +msgstr "Я хочу указать удалённую конфигурацию URI" #: ../gtk/setupwizard.c:89 msgid "Enter your linphone.org username" -msgstr "Введите ваше имя пользователя на linphone.org" +msgstr "Введите ваше имя пользователя для linphone.org" -#: ../gtk/setupwizard.c:96 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 +#: ../gtk/setupwizard.c:102 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 msgid "Username:" msgstr "Имя пользователя:" -#: ../gtk/setupwizard.c:98 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 +#: ../gtk/setupwizard.c:104 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 msgid "Password:" msgstr "Пароль:" -#: ../gtk/setupwizard.c:118 +#: ../gtk/setupwizard.c:124 msgid "Enter your account informations" -msgstr "Введите информацию о вашей учётной записи" +msgstr "Введите вашу информацию об учётной записи" -#: ../gtk/setupwizard.c:125 +#: ../gtk/setupwizard.c:140 msgid "Username*" msgstr "Имя пользователя*" -#: ../gtk/setupwizard.c:126 +#: ../gtk/setupwizard.c:141 msgid "Password*" msgstr "Пароль*" -#: ../gtk/setupwizard.c:129 +#: ../gtk/setupwizard.c:144 msgid "Domain*" msgstr "Домен*" -#: ../gtk/setupwizard.c:130 +#: ../gtk/setupwizard.c:145 msgid "Proxy" msgstr "Прокси" -#: ../gtk/setupwizard.c:302 +#: ../gtk/setupwizard.c:317 msgid "(*) Required fields" msgstr "(*) Обязательные поля" -#: ../gtk/setupwizard.c:303 +#: ../gtk/setupwizard.c:318 msgid "Username: (*)" msgstr "Имя пользователя: (*)" -#: ../gtk/setupwizard.c:305 +#: ../gtk/setupwizard.c:320 msgid "Password: (*)" msgstr "Пароль: (*)" -#: ../gtk/setupwizard.c:307 +#: ../gtk/setupwizard.c:322 msgid "Email: (*)" -msgstr "Email: (*)" +msgstr "Электронная почта: (*)" -#: ../gtk/setupwizard.c:309 +#: ../gtk/setupwizard.c:324 msgid "Confirm your password: (*)" msgstr "Подтвердите ваш пароль: (*)" -#: ../gtk/setupwizard.c:373 +#: ../gtk/setupwizard.c:338 +msgid "Keep me informed with linphone updates" +msgstr "Информировать об обновлениях linphone" + +#: ../gtk/setupwizard.c:394 msgid "" "Error, account not validated, username already used or server unreachable.\n" "Please go back and try again." msgstr "" -"Ошибка, непроверенная учётная запись, имя пользователя уже существует или " -"сервер недоступен.\n" -"Вернитесь и попробуйте ещё раз." +"Ошибка, учётная запись не подтверждена, имя пользователя уже используется " +"или\n" +"сервер недоступен. Пожалуйста, зайдите снова и попробуйте ещё раз." -#: ../gtk/setupwizard.c:384 +#: ../gtk/setupwizard.c:405 msgid "Thank you. Your account is now configured and ready for use." -msgstr "Спасибо! Учетная запись успешно настроена и готова к использованию." +msgstr "Спасибо! Учётная запись успешно настроена и готова к использованию." -#: ../gtk/setupwizard.c:392 +#: ../gtk/setupwizard.c:413 msgid "" "Please validate your account by clicking on the link we just sent you by " "email.\n" "Then come back here and press Next button." msgstr "" -"Пожалуйста, подтвердите свою учётную запись, пройдя по ссылке, которую мы " -"только что выслали вам на электронную почту.\n" -"Затем вернитесь и нажмите на кнопку Далее." +"Пожалуйста, подтвердите вашу учётную запись, щёлкнув на ссылку, которую вы " +"только\n" +"что получили по электронной почте. Затем вернитесь сюда и нажмите кнопку " +"Далее." -#: ../gtk/setupwizard.c:564 -#, fuzzy +#: ../gtk/setupwizard.c:600 msgid "SIP account configuration assistant" -msgstr "Помощник настройки учётной записи" +msgstr "Помощник настройки учётной записи SIP" -#: ../gtk/setupwizard.c:582 +#: ../gtk/setupwizard.c:618 msgid "Welcome to the account setup assistant" msgstr "Добро пожаловать в помощник настройки учётной записи" -#: ../gtk/setupwizard.c:587 +#: ../gtk/setupwizard.c:623 msgid "Account setup assistant" msgstr "Помощник настройки учётной записи" -#: ../gtk/setupwizard.c:593 +#: ../gtk/setupwizard.c:629 msgid "Configure your account (step 1/1)" -msgstr "Настройте свою учётную запись (шаг 1/1)" +msgstr "Настроить вашу учётную запись (шаг 1/1)" -#: ../gtk/setupwizard.c:598 +#: ../gtk/setupwizard.c:634 msgid "Enter your sip username (step 1/1)" -msgstr "Введите ваше имя пользователя SIP (шаг 1/1)" +msgstr "Введите ваше sip имя пользователя (шаг 1/1)" -#: ../gtk/setupwizard.c:602 +#: ../gtk/setupwizard.c:638 msgid "Enter account information (step 1/2)" -msgstr "Введи информация об учётной записи (шаг 1/2)" +msgstr "Введите информацию об учётной записи (шаг 1/2)" -#: ../gtk/setupwizard.c:611 +#: ../gtk/setupwizard.c:647 msgid "Validation (step 2/2)" -msgstr "Проверка (шаг 2/2)" +msgstr "Подтверждение (шаг 2/2)" -#: ../gtk/setupwizard.c:616 +#: ../gtk/setupwizard.c:652 msgid "Error" msgstr "Ошибка" -#: ../gtk/setupwizard.c:620 ../gtk/audio_assistant.c:519 +#: ../gtk/setupwizard.c:656 ../gtk/audio_assistant.c:527 msgid "Terminating" -msgstr "Завершение" +msgstr "Прерывание" #: ../gtk/incall_view.c:70 ../gtk/incall_view.c:94 #, c-format msgid "Call #%i" -msgstr "Вызов #%i" +msgstr "Звонок #%i" #: ../gtk/incall_view.c:155 #, c-format msgid "Transfer to call #%i with %s" -msgstr "Перевести на #%i с %s" +msgstr "Передача позвонить #%i с %s" #: ../gtk/incall_view.c:211 ../gtk/incall_view.c:214 -#, fuzzy msgid "Not used" -msgstr "Не найден" +msgstr "Не используется" #: ../gtk/incall_view.c:221 msgid "ICE not activated" -msgstr "" +msgstr "ICE не активировано" #: ../gtk/incall_view.c:223 -#, fuzzy msgid "ICE failed" -msgstr "ICE фильтр" +msgstr "Неудача ICE" #: ../gtk/incall_view.c:225 msgid "ICE in progress" -msgstr "" +msgstr "ICE в прогрессе" #: ../gtk/incall_view.c:227 msgid "Going through one or more NATs" -msgstr "" +msgstr "Пройти через один или несколько NAT" #: ../gtk/incall_view.c:229 -#, fuzzy msgid "Direct" -msgstr "Переадресован" +msgstr "Напрямую" #: ../gtk/incall_view.c:231 msgid "Through a relay server" -msgstr "" +msgstr "Через сервер ретрансляции" #: ../gtk/incall_view.c:239 msgid "uPnP not activated" -msgstr "" +msgstr "uPnP не активировано" #: ../gtk/incall_view.c:241 -#, fuzzy msgid "uPnP in progress" -msgstr "Идет поиск Stun..." +msgstr "uPnP в прогрессе" #: ../gtk/incall_view.c:243 -#, fuzzy msgid "uPnp not available" -msgstr "недоступно" +msgstr "uPnp недоступен" #: ../gtk/incall_view.c:245 msgid "uPnP is running" -msgstr "" +msgstr "uPnP выполняется" #: ../gtk/incall_view.c:247 -#, fuzzy msgid "uPnP failed" -msgstr "ICE фильтр" +msgstr "Неудача uPnP" #: ../gtk/incall_view.c:257 ../gtk/incall_view.c:258 msgid "Direct or through server" -msgstr "" +msgstr "Напрямую или через сервер" -#: ../gtk/incall_view.c:266 ../gtk/incall_view.c:276 +#: ../gtk/incall_view.c:267 ../gtk/incall_view.c:279 #, c-format msgid "" "download: %f\n" "upload: %f (kbit/s)" msgstr "" +"загрузка: %f\n" +"отдача: %f (КБит/сек)" -#: ../gtk/incall_view.c:271 ../gtk/incall_view.c:272 +#: ../gtk/incall_view.c:272 ../gtk/incall_view.c:274 #, c-format -msgid "%ix%i" -msgstr "" +msgid "%ix%i @ %f fps" +msgstr "%ix%i @ %f кадр/сек" -#: ../gtk/incall_view.c:301 -#, fuzzy, c-format +#: ../gtk/incall_view.c:304 +#, c-format msgid "%.3f seconds" -msgstr "%i секунда" +msgstr "%.3f секунд" -#: ../gtk/incall_view.c:399 ../gtk/main.ui.h:12 +#: ../gtk/incall_view.c:407 ../gtk/main.ui.h:12 msgid "Hang up" -msgstr "" +msgstr "Повесить трубку" -#: ../gtk/incall_view.c:492 +#: ../gtk/incall_view.c:501 msgid "Calling..." -msgstr "Вызов..." +msgstr "Звоним..." -#: ../gtk/incall_view.c:495 ../gtk/incall_view.c:698 +#: ../gtk/incall_view.c:504 ../gtk/incall_view.c:707 msgid "00::00::00" msgstr "00::00::00" -#: ../gtk/incall_view.c:506 +#: ../gtk/incall_view.c:515 msgid "Incoming call" -msgstr "Входящий вызов" +msgstr "Входящий звонок" -#: ../gtk/incall_view.c:543 +#: ../gtk/incall_view.c:552 msgid "good" -msgstr "хорошее" +msgstr "хороший" -#: ../gtk/incall_view.c:545 +#: ../gtk/incall_view.c:554 msgid "average" -msgstr "среднее" +msgstr "средний" -#: ../gtk/incall_view.c:547 +#: ../gtk/incall_view.c:556 msgid "poor" -msgstr "плохое" +msgstr "плохой" -#: ../gtk/incall_view.c:549 +#: ../gtk/incall_view.c:558 msgid "very poor" -msgstr "очень плохое" +msgstr "очень плохой" -#: ../gtk/incall_view.c:551 +#: ../gtk/incall_view.c:560 msgid "too bad" -msgstr "слишком плохое" +msgstr "совсем плохой" -#: ../gtk/incall_view.c:552 ../gtk/incall_view.c:568 +#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:577 msgid "unavailable" -msgstr "недоступно" +msgstr "недоступен" -#: ../gtk/incall_view.c:660 +#: ../gtk/incall_view.c:669 msgid "Secured by SRTP" -msgstr "Защищено SRTP" +msgstr "Защищённые с помощью SRTP" -#: ../gtk/incall_view.c:666 +#: ../gtk/incall_view.c:675 #, c-format msgid "Secured by ZRTP - [auth token: %s]" -msgstr "Защищено ZRTP - [токен: %s]" +msgstr "Защищённые с помощью ZRTP - [знак аутентификации: %s]" -#: ../gtk/incall_view.c:672 +#: ../gtk/incall_view.c:681 msgid "Set unverified" -msgstr "Не проверен" +msgstr "Установить непроверенный" -#: ../gtk/incall_view.c:672 ../gtk/main.ui.h:4 +#: ../gtk/incall_view.c:681 ../gtk/main.ui.h:4 msgid "Set verified" -msgstr "Проверен" +msgstr "Установить проверенный" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In conference" msgstr "В конференции" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In call" -msgstr "Соединен с" +msgstr "Звоним" -#: ../gtk/incall_view.c:729 +#: ../gtk/incall_view.c:738 msgid "Paused call" -msgstr "Приостановленный вызов" +msgstr "Звонок приостановлен" -#: ../gtk/incall_view.c:742 +#: ../gtk/incall_view.c:751 #, c-format msgid "%02i::%02i::%02i" msgstr "%02i::%02i::%02i" -#: ../gtk/incall_view.c:760 +#: ../gtk/incall_view.c:772 msgid "Call ended." msgstr "Звонок закончен." -#: ../gtk/incall_view.c:791 +#: ../gtk/incall_view.c:803 msgid "Transfer in progress" -msgstr "" +msgstr "Передача в прогрессе" -#: ../gtk/incall_view.c:794 -#, fuzzy +#: ../gtk/incall_view.c:806 msgid "Transfer done." -msgstr "Перевести" +msgstr "Передача завершена." -#: ../gtk/incall_view.c:797 -#, fuzzy +#: ../gtk/incall_view.c:809 msgid "Transfer failed." -msgstr "Перевести" +msgstr "Передача неудачна." -#: ../gtk/incall_view.c:841 +#: ../gtk/incall_view.c:853 msgid "Resume" msgstr "Продолжить" -#: ../gtk/incall_view.c:848 ../gtk/main.ui.h:9 +#: ../gtk/incall_view.c:860 ../gtk/main.ui.h:9 msgid "Pause" msgstr "Пауза" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, c-format msgid "" "Recording into\n" "%s %s" msgstr "" +"Записывается в\n" +"%s %s" -#: ../gtk/incall_view.c:913 -#, fuzzy +#: ../gtk/incall_view.c:926 msgid "(Paused)" -msgstr "Пауза" +msgstr "(Пауза)" #: ../gtk/loginframe.c:88 #, c-format msgid "Please enter login information for %s" -msgstr "Введите информацию для входа %s" +msgstr "Пожалуйста, введите информацию для входа %s:" #: ../gtk/config-fetching.c:57 -#, fuzzy, c-format +#, c-format msgid "fetching from %s" -msgstr "Входящий звонок от %s" +msgstr "получение от %s" #: ../gtk/config-fetching.c:73 #, c-format msgid "Downloading of remote configuration from %s failed." -msgstr "" +msgstr "Загрузка удалённой конфигурации из %s неудачна." #: ../gtk/audio_assistant.c:98 msgid "No voice detected" -msgstr "" +msgstr "Голос не обнаружен" #: ../gtk/audio_assistant.c:99 msgid "Too low" -msgstr "" +msgstr "Слишком тихо" #: ../gtk/audio_assistant.c:100 msgid "Good" -msgstr "" +msgstr "Хорошо" #: ../gtk/audio_assistant.c:101 msgid "Too loud" -msgstr "" +msgstr "Слишком громко" -#: ../gtk/audio_assistant.c:316 -#, fuzzy +#: ../gtk/audio_assistant.c:318 msgid "" "Welcome !\n" "This assistant will help you to configure audio settings for Linphone" msgstr "" "Добро пожаловать!\n" -"Этот помощник поможет вам использовать учётную запись SIP для ваших звонков." +"Этот помощник поможет вам сконфигурировать настройки аудио для linphone" -#: ../gtk/audio_assistant.c:326 -#, fuzzy +#: ../gtk/audio_assistant.c:328 msgid "Capture device" -msgstr "Устройство захвата:" +msgstr "Устройство захвата" -#: ../gtk/audio_assistant.c:327 -#, fuzzy +#: ../gtk/audio_assistant.c:329 msgid "Recorded volume" -msgstr "Источник записи:" +msgstr "Уровень записи" -#: ../gtk/audio_assistant.c:331 +#: ../gtk/audio_assistant.c:333 msgid "No voice" -msgstr "" +msgstr "Нет голоса" -#: ../gtk/audio_assistant.c:367 -#, fuzzy +#: ../gtk/audio_assistant.c:369 msgid "Playback device" -msgstr "Устройство воспроизведения:" +msgstr "Устройство воспроизведения" -#: ../gtk/audio_assistant.c:368 +#: ../gtk/audio_assistant.c:370 msgid "Play three beeps" -msgstr "" +msgstr "Проиграть три сигнала" -#: ../gtk/audio_assistant.c:400 +#: ../gtk/audio_assistant.c:403 msgid "Press the record button and say some words" -msgstr "" +msgstr "Нажмите кнопку записи и скажите несколько слов" -#: ../gtk/audio_assistant.c:401 +#: ../gtk/audio_assistant.c:404 msgid "Listen to your record voice" -msgstr "" +msgstr "Прослушайте ваш записанный голос" -#: ../gtk/audio_assistant.c:430 +#: ../gtk/audio_assistant.c:433 msgid "Let's start Linphone now" -msgstr "" +msgstr "Давайте сейчас запустим linphone" -#: ../gtk/audio_assistant.c:488 -#, fuzzy +#: ../gtk/audio_assistant.c:496 msgid "Audio Assistant" -msgstr "Помощник" +msgstr "Помощник аудио" -#: ../gtk/audio_assistant.c:498 ../gtk/main.ui.h:31 -#, fuzzy +#: ../gtk/audio_assistant.c:506 ../gtk/main.ui.h:31 msgid "Audio assistant" -msgstr "Помощник настройки учётной записи" +msgstr "Помощник аудио" -#: ../gtk/audio_assistant.c:503 +#: ../gtk/audio_assistant.c:511 msgid "Mic Gain calibration" -msgstr "" +msgstr "Калибровка усиления микрофона" -#: ../gtk/audio_assistant.c:509 +#: ../gtk/audio_assistant.c:517 msgid "Speaker volume calibration" -msgstr "" +msgstr "Калибровка громкости динамика" -#: ../gtk/audio_assistant.c:514 +#: ../gtk/audio_assistant.c:522 msgid "Record and Play" -msgstr "" +msgstr "Записать и проиграть" #: ../gtk/main.ui.h:1 msgid "Callee name" -msgstr "Имя вызываемого абонента" +msgstr "Имя вызываемого" #: ../gtk/main.ui.h:2 msgid "Send" msgstr "Отправить" #: ../gtk/main.ui.h:3 -#, fuzzy msgid "End conference" -msgstr "В конференции" +msgstr "Конец конференции" #: ../gtk/main.ui.h:7 msgid "Record this call to an audio file" -msgstr "" +msgstr "Записать этот вызов в аудио файл" #: ../gtk/main.ui.h:8 msgid "Video" -msgstr "" +msgstr "Видео" #: ../gtk/main.ui.h:10 msgid "Mute" -msgstr "" +msgstr "Без звука" #: ../gtk/main.ui.h:11 msgid "Transfer" -msgstr "Перевести" +msgstr "Передача" #: ../gtk/main.ui.h:14 msgid "In call" -msgstr "Вызов" +msgstr "Входящий звонок" #: ../gtk/main.ui.h:15 msgid "Duration" @@ -921,7 +906,7 @@ msgstr "Продолжительность" #: ../gtk/main.ui.h:16 msgid "Call quality rating" -msgstr "Уровень качества звонка" +msgstr "Вызвать рейтинг качества" #: ../gtk/main.ui.h:17 msgid "All users" @@ -937,7 +922,7 @@ msgstr "ADSL" #: ../gtk/main.ui.h:20 msgid "Fiber Channel" -msgstr "Оптоволокно" +msgstr "Оптоволоконный канал" #: ../gtk/main.ui.h:21 msgid "Default" @@ -945,20 +930,19 @@ msgstr "По умолчанию" #: ../gtk/main.ui.h:22 msgid "_Options" -msgstr "_Настройки" +msgstr "_Опции" #: ../gtk/main.ui.h:23 -#, fuzzy msgid "Set configuration URI" -msgstr "Прокси/Регистратор конфигуратор" +msgstr "Установить конфигурацию URI" #: ../gtk/main.ui.h:24 msgid "Always start video" -msgstr "" +msgstr "Всегда запускать видео" #: ../gtk/main.ui.h:25 msgid "Enable self-view" -msgstr "Включить своё видео" +msgstr "Показать окно видео" #: ../gtk/main.ui.h:26 msgid "_Help" @@ -974,11 +958,11 @@ msgstr "_Домашняя страница" #: ../gtk/main.ui.h:29 msgid "Check _Updates" -msgstr "Проверить _Обновления" +msgstr "Проверить _обновления" #: ../gtk/main.ui.h:30 msgid "Account assistant" -msgstr "Помощник настройки учётной записи" +msgstr "Помощник учётной записи" #: ../gtk/main.ui.h:32 msgid "SIP address or phone number:" @@ -986,7 +970,7 @@ msgstr "SIP-адрес или номер телефона:" #: ../gtk/main.ui.h:33 msgid "Initiate a new call" -msgstr "Совершить новый вызов" +msgstr "Начать новый звонок" #: ../gtk/main.ui.h:34 msgid "Contacts" @@ -1006,7 +990,7 @@ msgstr "Добавить контакт" #: ../gtk/main.ui.h:38 msgid "Recent calls" -msgstr "Недавние вызовы" +msgstr "Последние звонки" #: ../gtk/main.ui.h:39 msgid "My current identity:" @@ -1030,7 +1014,7 @@ msgstr "Входить автоматически" #: ../gtk/main.ui.h:44 ../gtk/password.ui.h:3 msgid "UserID" -msgstr "UserID" +msgstr "Идентификатор пользователя" #: ../gtk/main.ui.h:45 msgid "Login information" @@ -1042,7 +1026,7 @@ msgstr "Добро пожаловать!" #: ../gtk/main.ui.h:47 msgid "Delete" -msgstr "" +msgstr "Удалить" #: ../gtk/about.ui.h:1 msgid "About linphone" @@ -1054,11 +1038,9 @@ msgstr "(C) Belledonne Communications,2010\n" #: ../gtk/about.ui.h:4 msgid "An internet video phone using the standard SIP (rfc3261) protocol." -msgstr "" -"Видео-телефон для интернета, использующий стандартный протокол SIP (rfc3261)." +msgstr "Интернет видео телефон, использующий стандарт протокола SIP (rfc3261)." #: ../gtk/about.ui.h:5 -#, fuzzy msgid "" "fr: Simon Morlat\n" "en: Simon Morlat and Delphine Perreau\n" @@ -1084,18 +1066,19 @@ msgstr "" "pl: Robert Nasiadek \n" "cs: Petr Pisar \n" "hu: anonymous\n" +"he: Eli Zaretskii \n" #: ../gtk/contact.ui.h:2 msgid "SIP Address" -msgstr "SIP-адрес" +msgstr "SIP адрес" #: ../gtk/contact.ui.h:3 msgid "Show this contact presence status" -msgstr "Показывать статус присутствия этого контакта" +msgstr "Показывать этому контакту статус присутствия" #: ../gtk/contact.ui.h:4 msgid "Allow this contact to see my presence status" -msgstr "Разрешить этому контакту видеть статус моего присутствия" +msgstr "Разрешить этому контакту видеть мой статус присутствия" #: ../gtk/contact.ui.h:5 msgid "Contact information" @@ -1107,15 +1090,15 @@ msgstr "Окно отладки linphone" #: ../gtk/log.ui.h:2 msgid "Scroll to end" -msgstr "Прокрутите до конца" +msgstr "Прокрутка в конец" #: ../gtk/password.ui.h:1 msgid "Linphone - Authentication required" -msgstr "Linphone - Необходима аутентификация" +msgstr "Linphone - необходима регистрация" #: ../gtk/password.ui.h:2 msgid "Please enter the domain password" -msgstr "Введите пароль" +msgstr "Введите пароль для домена" #: ../gtk/call_logs.ui.h:1 msgid "Call history" @@ -1127,19 +1110,19 @@ msgstr "Очистить всё" #: ../gtk/call_logs.ui.h:3 msgid "Call back" -msgstr "Перезвонить" +msgstr "Позвонить повторно" #: ../gtk/sip_account.ui.h:1 msgid "Linphone - Configure a SIP account" -msgstr "Linphone - Настроить учётную запись SIP" +msgstr "Linphone - настроить учётную запись SIP" #: ../gtk/sip_account.ui.h:2 msgid "Your SIP identity:" -msgstr "Идентификатор SIP:" +msgstr "Ваш идентификатор SIP:" #: ../gtk/sip_account.ui.h:3 msgid "Looks like sip:@" -msgstr "Похоже на sip:@" +msgstr "Выглядит как sip:<имя_пользователя>@<домен>" #: ../gtk/sip_account.ui.h:4 msgid "sip:" @@ -1147,46 +1130,43 @@ msgstr "sip:" #: ../gtk/sip_account.ui.h:5 msgid "SIP Proxy address:" -msgstr "Адрес SIP-прокси:" +msgstr "Адрес SIP прокси:" #: ../gtk/sip_account.ui.h:6 msgid "Looks like sip:" -msgstr "Похоже на sip:" +msgstr "Выглядит как sip:<прокси имя_хоста>" #: ../gtk/sip_account.ui.h:7 msgid "Registration duration (sec):" msgstr "Продолжительность регистрации (сек):" #: ../gtk/sip_account.ui.h:8 -#, fuzzy msgid "Contact params (optional):" -msgstr "Маршрут (необязательно):" +msgstr "Параметры контакта (опционально):" #: ../gtk/sip_account.ui.h:9 msgid "AVPF regular RTCP interval (sec):" -msgstr "" +msgstr "AVPF постоянный интервал RTCP (сек):" #: ../gtk/sip_account.ui.h:10 msgid "Route (optional):" -msgstr "Маршрут (необязательно):" +msgstr "Маршрут (опционально):" #: ../gtk/sip_account.ui.h:11 -#, fuzzy msgid "Transport" -msgstr "Транспорт" +msgstr "Транспорт" #: ../gtk/sip_account.ui.h:12 msgid "Register" -msgstr "Зарегистрироваться" +msgstr "Регистрация" #: ../gtk/sip_account.ui.h:13 msgid "Publish presence information" -msgstr "Опубликовывать статус присутствия" +msgstr "Опубликовать статус присутствия" #: ../gtk/sip_account.ui.h:14 -#, fuzzy msgid "Enable AVPF" -msgstr "Включить" +msgstr "Разрешить AVPF" #: ../gtk/sip_account.ui.h:15 msgid "Configure a SIP account" @@ -1194,15 +1174,15 @@ msgstr "Настроить учётную запись SIP" #: ../gtk/parameters.ui.h:1 msgid "anonymous" -msgstr "" +msgstr "аноним" #: ../gtk/parameters.ui.h:2 msgid "GSSAPI" -msgstr "" +msgstr "GSSAPI" #: ../gtk/parameters.ui.h:3 msgid "SASL" -msgstr "" +msgstr "SASL" #: ../gtk/parameters.ui.h:4 msgid "default soundcard" @@ -1214,7 +1194,7 @@ msgstr "звуковая карта" #: ../gtk/parameters.ui.h:6 msgid "default camera" -msgstr "камера по умолчаию" +msgstr "камера по умолчанию" #: ../gtk/parameters.ui.h:7 msgid "CIF" @@ -1250,11 +1230,11 @@ msgstr "Настройки" #: ../gtk/parameters.ui.h:15 msgid "Set Maximum Transmission Unit:" -msgstr "Установить MTU:" +msgstr "Установить MTU (максимально передаваемый блок):" #: ../gtk/parameters.ui.h:16 msgid "Send DTMFs as SIP info" -msgstr "Отправлять DTFM как SIP Info" +msgstr "Отправлять DTFM как SIP-информацию" #: ../gtk/parameters.ui.h:17 msgid "Use IPv6 instead of IPv4" @@ -1266,7 +1246,7 @@ msgstr "Транспорт" #: ../gtk/parameters.ui.h:19 msgid "Media encryption type" -msgstr "Тип шифрования потока" +msgstr "Тип медиа-шифрования" #: ../gtk/parameters.ui.h:20 msgid "Video RTP/UDP:" @@ -1278,65 +1258,59 @@ msgstr "Аудио RTP/UDP:" #: ../gtk/parameters.ui.h:22 msgid "Fixed" -msgstr "" +msgstr "Фиксированный" #: ../gtk/parameters.ui.h:23 -#, fuzzy msgid "Media encryption is mandatory" -msgstr "Тип шифрования потока" +msgstr "Медиа-шифрование обязательно" #: ../gtk/parameters.ui.h:24 msgid "Tunnel" -msgstr "Туннель" +msgstr "Тунель" #: ../gtk/parameters.ui.h:25 msgid "DSCP fields" -msgstr "" +msgstr "Поля DSCP" #: ../gtk/parameters.ui.h:26 -#, fuzzy msgid "SIP/TCP port" -msgstr "SIP порт" +msgstr "Порт SIP/TCP" #: ../gtk/parameters.ui.h:27 -#, fuzzy msgid "SIP/UDP port" -msgstr "SIP порт" +msgstr "Порт SIP/UDP" #: ../gtk/parameters.ui.h:28 msgid "Network protocol and ports" -msgstr "Протокол и порты" +msgstr "Сетевые протоколы и порты" #: ../gtk/parameters.ui.h:29 msgid "Direct connection to the Internet" -msgstr "Прямое подключение к Интернету" +msgstr "Прямое подключение к интернет" #: ../gtk/parameters.ui.h:30 -#, fuzzy msgid "Behind NAT / Firewall (specify gateway IP )" -msgstr "За NAT / брандмауэром (укажите IP-адрес шлюза ниже)" +msgstr "За NAT / брандмауэром (указать IP шлюза)" #: ../gtk/parameters.ui.h:31 msgid "Behind NAT / Firewall (use STUN to resolve)" msgstr "За NAT / брандмауэром (использовать STUN)" #: ../gtk/parameters.ui.h:32 -#, fuzzy msgid "Behind NAT / Firewall (use ICE)" -msgstr "За NAT / брандмауэром (использовать STUN)" +msgstr "За NAT / брандмауэром (использовать ICE)" #: ../gtk/parameters.ui.h:33 -#, fuzzy msgid "Behind NAT / Firewall (use uPnP)" -msgstr "За NAT / брандмауэром (использовать STUN)" +msgstr "За NAT / брандмауэром (использовать uPnP)" #: ../gtk/parameters.ui.h:34 msgid "Public IP address:" -msgstr "Внешний IP-адрес:" +msgstr "Выделенный (публичный) IP-адрес:" #: ../gtk/parameters.ui.h:35 msgid "Stun server:" -msgstr "Сервер STUN:" +msgstr "STUN сервер:" #: ../gtk/parameters.ui.h:36 msgid "NAT and Firewall" @@ -1348,11 +1322,11 @@ msgstr "Настройки сети" #: ../gtk/parameters.ui.h:38 msgid "Ring sound:" -msgstr "Звук звонка:" +msgstr "Мелодия звонка:" #: ../gtk/parameters.ui.h:39 msgid "ALSA special device (optional):" -msgstr "Специальное устройство ALSA (необязательно):" +msgstr "Специальное устройство ALSA (опционально)" #: ../gtk/parameters.ui.h:40 msgid "Capture device:" @@ -1368,24 +1342,23 @@ msgstr "Устройство воспроизведения:" #: ../gtk/parameters.ui.h:43 msgid "Enable echo cancellation" -msgstr "Включить подавление эхо" +msgstr "Разрешить подавление эха" #: ../gtk/parameters.ui.h:44 msgid "Audio" -msgstr "Звук" +msgstr "Аудио" #: ../gtk/parameters.ui.h:45 msgid "Video input device:" -msgstr "Устройство захвата видео:" +msgstr "Устройство для вывода видео:" #: ../gtk/parameters.ui.h:46 msgid "Prefered video resolution:" msgstr "Предпочтительное разрешение видео:" #: ../gtk/parameters.ui.h:47 -#, fuzzy msgid "Video output method:" -msgstr "Устройство захвата видео:" +msgstr "Метод вывода видео:" #: ../gtk/parameters.ui.h:48 msgid "Video" @@ -1398,19 +1371,20 @@ msgstr "Настройки мультимедиа" #: ../gtk/parameters.ui.h:50 msgid "This section defines your SIP address when not using a SIP account" msgstr "" -"Эта секция устанавливает ваш SIP-адрес, когда вы не используете SIP-аккаунт" +"Эта секция определяет ваш SIP адрес, когда вы не используете учётную запись " +"SIP" #: ../gtk/parameters.ui.h:51 msgid "Your display name (eg: John Doe):" -msgstr "Отображаемое имя (напр.: Иван Сидоров):" +msgstr "Отображаемое имя (например: Иван Сидоров):" #: ../gtk/parameters.ui.h:52 msgid "Your username:" -msgstr "Имя пользователя:" +msgstr "Ваше имя пользователя:" #: ../gtk/parameters.ui.h:53 msgid "Your resulting SIP address:" -msgstr "Результирующий SIP-адрес:" +msgstr "Ваш результирующий SIP адрес:" #: ../gtk/parameters.ui.h:54 msgid "Default identity" @@ -1434,7 +1408,7 @@ msgstr "Удалить" #: ../gtk/parameters.ui.h:59 msgid "Proxy accounts" -msgstr "Учетные записи прокси" +msgstr "Учётные записи" #: ../gtk/parameters.ui.h:60 msgid "Erase all passwords" @@ -1442,7 +1416,7 @@ msgstr "Стереть все пароли" #: ../gtk/parameters.ui.h:61 msgid "Privacy" -msgstr "Конфеденциальность" +msgstr "Секретность" #: ../gtk/parameters.ui.h:62 msgid "Manage SIP Accounts" @@ -1450,7 +1424,7 @@ msgstr "Управление учётными записями SIP" #: ../gtk/parameters.ui.h:63 ../gtk/tunnel_config.ui.h:4 msgid "Enable" -msgstr "Включить" +msgstr "Разрешить" #: ../gtk/parameters.ui.h:64 ../gtk/tunnel_config.ui.h:5 msgid "Disable" @@ -1466,27 +1440,27 @@ msgstr "0 означает \"безлимитный\"" #: ../gtk/parameters.ui.h:67 msgid "Upload speed limit in Kbit/sec:" -msgstr "Ограничение исходящего потока в кбит/сек:" +msgstr "Ограничение исходящего потока КБит/сек:" #: ../gtk/parameters.ui.h:68 msgid "Download speed limit in Kbit/sec:" -msgstr "Ограничение скорости входящего потока в кбит/сек" +msgstr "Ограничение скорости входящего потока КБит/сек:" #: ../gtk/parameters.ui.h:69 msgid "Enable adaptive rate control" -msgstr "Включить адаптивный контроль скорости" +msgstr "Разрешить адаптивное управление скоростью" #: ../gtk/parameters.ui.h:70 msgid "" "Adaptive rate control is a technique to dynamically guess the available " "bandwidth during a call." msgstr "" -"Адаптивное управление скоростью - это техника, позволяющая динамически " -"определять доступную пропускную способность сети во время звонка." +"Адаптивное управление скоростью - это технология динамического угадывания " +"доступной пропускной способности во время звонка." #: ../gtk/parameters.ui.h:71 msgid "Bandwidth control" -msgstr "Управление скоростью сети" +msgstr "Пропускная способность" #: ../gtk/parameters.ui.h:72 msgid "Codecs" @@ -1498,7 +1472,7 @@ msgstr "Язык" #: ../gtk/parameters.ui.h:74 msgid "Show advanced settings" -msgstr "Показывать расширенные настройки" +msgstr "Показать дополнительные настройки" #: ../gtk/parameters.ui.h:75 msgid "Level" @@ -1506,30 +1480,27 @@ msgstr "Уровень" #: ../gtk/parameters.ui.h:76 msgid "User interface" -msgstr "Интерфейс пользователя" +msgstr "Пользовательский интерфейс" #: ../gtk/parameters.ui.h:77 ../gtk/ldap.ui.h:2 -#, fuzzy msgid "Server address:" -msgstr "Server-Adresse:" +msgstr "Адрес сервера:" #: ../gtk/parameters.ui.h:78 ../gtk/ldap.ui.h:3 -#, fuzzy msgid "Authentication method:" -msgstr "Ошибка аутентификации" +msgstr "Метод аутентификации:" #: ../gtk/parameters.ui.h:80 msgid "label" msgstr "метка" #: ../gtk/parameters.ui.h:81 -#, fuzzy msgid "LDAP Account setup" -msgstr "Учетные записи прокси" +msgstr "Установка учётной записи LDAP" #: ../gtk/parameters.ui.h:82 msgid "LDAP" -msgstr "" +msgstr "LDAP" #: ../gtk/parameters.ui.h:83 msgid "Done" @@ -1537,7 +1508,7 @@ msgstr "Готово" #: ../gtk/buddylookup.ui.h:1 msgid "Search contacts in directory" -msgstr "Искать контакты в директории" +msgstr "Поиск контактов в директории" #: ../gtk/buddylookup.ui.h:2 msgid "Add to my list" @@ -1545,7 +1516,7 @@ msgstr "Добавить в мой список" #: ../gtk/buddylookup.ui.h:3 msgid "Search somebody" -msgstr "Найти кого-нибудь" +msgstr "Поиск кого-нибудь" #: ../gtk/waiting.ui.h:1 msgid "Linphone" @@ -1553,108 +1524,95 @@ msgstr "Linphone" #: ../gtk/waiting.ui.h:2 msgid "Please wait" -msgstr "Подождите" +msgstr "Пожалуйста, подождите" #: ../gtk/dscp_settings.ui.h:1 -#, fuzzy msgid "DSCP settings" -msgstr "Настройки" +msgstr "Настройки DSCP" #: ../gtk/dscp_settings.ui.h:2 msgid "SIP" msgstr "SIP" #: ../gtk/dscp_settings.ui.h:3 -#, fuzzy msgid "Audio RTP stream" -msgstr "Аудио RTP/UDP:" +msgstr "Аудио поток RTP" #: ../gtk/dscp_settings.ui.h:4 -#, fuzzy msgid "Video RTP stream" -msgstr "Видео RTP/UDP:" +msgstr "Видео поток RTP" #: ../gtk/dscp_settings.ui.h:5 msgid "Set DSCP values (in hexadecimal)" -msgstr "" +msgstr "Установить значения DSCP (в шестнадцатеричном формате)" #: ../gtk/call_statistics.ui.h:1 -#, fuzzy msgid "Call statistics" -msgstr "Звонк %s" +msgstr "Вызов статистики" #: ../gtk/call_statistics.ui.h:2 -#, fuzzy msgid "Audio codec" -msgstr "Аудио кодеки" +msgstr "Аудио кодек" #: ../gtk/call_statistics.ui.h:3 -#, fuzzy msgid "Video codec" -msgstr "Видео кодеки" +msgstr "Видео кодек" #: ../gtk/call_statistics.ui.h:4 msgid "Audio IP bandwidth usage" -msgstr "" +msgstr "Использование пропускной способности аудио IP" #: ../gtk/call_statistics.ui.h:5 -#, fuzzy msgid "Audio Media connectivity" -msgstr "Тип шифрования потока" +msgstr "Подключение медиа-аудио" #: ../gtk/call_statistics.ui.h:6 msgid "Video IP bandwidth usage" -msgstr "" +msgstr "Использование пропускной способности видео IP" #: ../gtk/call_statistics.ui.h:7 -#, fuzzy msgid "Video Media connectivity" -msgstr "Тип шифрования потока" +msgstr "Подключение медиа-видео" #: ../gtk/call_statistics.ui.h:8 -#, fuzzy msgid "Round trip time" -msgstr "Настройки звука" +msgstr "Округлять время в действии" #: ../gtk/call_statistics.ui.h:9 msgid "Video resolution received" -msgstr "" +msgstr "Получено разрешение видео" #: ../gtk/call_statistics.ui.h:10 -#, fuzzy msgid "Video resolution sent" -msgstr "Предпочтительное разрешение видео:" +msgstr "Разрешение видео отправлено" #: ../gtk/call_statistics.ui.h:11 -#, fuzzy msgid "RTP profile" -msgstr "RTP свойства" +msgstr "Профиль RTP" #: ../gtk/call_statistics.ui.h:12 -#, fuzzy msgid "Call statistics and information" -msgstr "Контактная информация" +msgstr "Вызов статистики и информации" #: ../gtk/tunnel_config.ui.h:1 -#, fuzzy msgid "Configure VoIP tunnel" -msgstr "Настроить учётную запись SIP" +msgstr "Настроить тунель VoIP" #: ../gtk/tunnel_config.ui.h:2 msgid "Host" -msgstr "" +msgstr "Хост" #: ../gtk/tunnel_config.ui.h:3 msgid "Port" -msgstr "" +msgstr "Порт" #: ../gtk/tunnel_config.ui.h:6 msgid "Configure tunnel" -msgstr "" +msgstr "Конфигурировать тунель" #: ../gtk/tunnel_config.ui.h:9 msgid "Configure http proxy (optional)" -msgstr "" +msgstr "Конфигурировать http прокси (опционально)" #: ../gtk/keypad.ui.h:1 msgid "D" @@ -1717,105 +1675,97 @@ msgid "1" msgstr "1" #: ../gtk/ldap.ui.h:1 -#, fuzzy msgid "LDAP Settings" -msgstr "Настройки" +msgstr "Настройки LDAP" #: ../gtk/ldap.ui.h:6 msgid "Use TLS Connection" -msgstr "" +msgstr "Использовать соединение TLS" #: ../gtk/ldap.ui.h:7 -#, fuzzy msgid "Not yet available" -msgstr "недоступно" +msgstr "Ещё недоступно" #: ../gtk/ldap.ui.h:8 -#, fuzzy msgid "Connection" -msgstr "Кодеки" +msgstr "Соединение" #: ../gtk/ldap.ui.h:9 msgid "Bind DN" -msgstr "" +msgstr "Привязать DN" #: ../gtk/ldap.ui.h:10 msgid "Authname" -msgstr "" +msgstr "Имя для аутентификации" #: ../gtk/ldap.ui.h:11 -#, fuzzy msgid "Realm" -msgstr "Название:" +msgstr "Реалм (рилм)" #: ../gtk/ldap.ui.h:12 -#, fuzzy msgid "SASL" -msgstr "Звук" +msgstr "SASL" #: ../gtk/ldap.ui.h:13 msgid "Base object:" -msgstr "" +msgstr "Базовый объект:" #: ../gtk/ldap.ui.h:15 #, no-c-format msgid "Filter (%s for name):" -msgstr "" +msgstr "Фильтр (%s для имени):" #: ../gtk/ldap.ui.h:16 msgid "Name Attribute:" -msgstr "" +msgstr "Атрибут имени:" #: ../gtk/ldap.ui.h:17 -#, fuzzy msgid "SIP address attribute:" -msgstr "SIP-адрес" +msgstr "Атрибут SIP-адреса:" #: ../gtk/ldap.ui.h:18 msgid "Attributes to query:" -msgstr "" +msgstr "Атрибуты для запроса:" #: ../gtk/ldap.ui.h:19 -#, fuzzy msgid "Search" -msgstr "Найти кого-нибудь" +msgstr "Поиск" #: ../gtk/ldap.ui.h:20 msgid "Timeout for search:" -msgstr "" +msgstr "Таймаут для поиска:" #: ../gtk/ldap.ui.h:21 msgid "Max results:" -msgstr "" +msgstr "Максимум результатов:" #: ../gtk/ldap.ui.h:22 msgid "Follow Aliases" -msgstr "" +msgstr "Следовать алиасам" #: ../gtk/ldap.ui.h:23 -#, fuzzy msgid "Miscellaneous" msgstr "Разное" #: ../gtk/ldap.ui.h:24 msgid "ANONYMOUS" -msgstr "" +msgstr "АНОНИМ" #: ../gtk/ldap.ui.h:25 msgid "SIMPLE" -msgstr "" +msgstr "ПРОСТОЙ" #: ../gtk/ldap.ui.h:26 msgid "DIGEST-MD5" -msgstr "" +msgstr "ДАЙДЖЕСТ-MD5" #: ../gtk/ldap.ui.h:27 msgid "NTLM" -msgstr "" +msgstr "NTLM" #: ../gtk/config-uri.ui.h:1 msgid "Specifying a remote configuration URI" -msgstr "" +msgstr "Указание удалённой конфигурации URI" #: ../gtk/config-uri.ui.h:2 msgid "" @@ -1825,120 +1775,93 @@ msgid "" "Linphone will restart automatically in order to fetch and take into account " "the new configuration. " msgstr "" +"Этот диалог позволяет установить HTTP или HTTPS адрес, когда конфигурация " +"будет получена при запуске.\n" +"Пожалуйста, введите или измените настройки URI ниже. После нажатия OK " +"linphone автоматически перезагрузится чтобы получить и учесть новую " +"конфигурацию в учётной записи." #: ../gtk/config-uri.ui.h:4 msgid "https://" -msgstr "" +msgstr "https://" #: ../gtk/provisioning-fetch.ui.h:1 -#, fuzzy msgid "Configuring..." -msgstr "Подключение..." +msgstr "Конфигурирование..." #: ../gtk/provisioning-fetch.ui.h:2 msgid "Please wait while fetching configuration from server..." -msgstr "" +msgstr "Пожалуйста, подождите пока получается конфигурация с сервера..." -#: ../coreapi/linphonecore.c:242 -msgid "aborted" -msgstr "отмененный" - -#: ../coreapi/linphonecore.c:245 -msgid "completed" -msgstr "завершённый" - -#: ../coreapi/linphonecore.c:248 -msgid "missed" -msgstr "пропущенный" - -#: ../coreapi/linphonecore.c:253 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" -"%s в %s\n" -"От: %s\n" -"Кому: %s\n" -"Статус: %s\n" -"Длительность: %i мин %i сек\n" - -#: ../coreapi/linphonecore.c:254 -msgid "Outgoing call" -msgstr "Исходящий звонок" - -#: ../coreapi/linphonecore.c:1287 +#: ../coreapi/linphonecore.c:1034 msgid "Ready" msgstr "Готов" -#: ../coreapi/linphonecore.c:2248 -#, fuzzy +#: ../coreapi/linphonecore.c:1967 msgid "Configuring" -msgstr "Подтверждение" +msgstr "Конфигурирование" -#: ../coreapi/linphonecore.c:2410 +#: ../coreapi/linphonecore.c:2133 msgid "Looking for telephone number destination..." -msgstr "Поиск адреса для телефонного номера..." +msgstr "Поиск назначения для телефонного номера.." -#: ../coreapi/linphonecore.c:2413 +#: ../coreapi/linphonecore.c:2136 msgid "Could not resolve this number." -msgstr "Не могу найти этот номер." +msgstr "Не получилось принять решение по этому номеру." #. must be known at that time -#: ../coreapi/linphonecore.c:2695 +#: ../coreapi/linphonecore.c:2418 msgid "Contacting" msgstr "Соединение" -#: ../coreapi/linphonecore.c:2702 +#: ../coreapi/linphonecore.c:2425 msgid "Could not call" -msgstr "Не удалось позвонить" +msgstr "Невозможно позвонить" -#: ../coreapi/linphonecore.c:2852 +#: ../coreapi/linphonecore.c:2576 msgid "Sorry, we have reached the maximum number of simultaneous calls" -msgstr "Извините, мы превысили максимальное количество одновременных вызовов" +msgstr "" +"К сожалению, мы достигли максимального количества одновременных звонков" -#: ../coreapi/linphonecore.c:3022 +#: ../coreapi/linphonecore.c:2745 msgid "is contacting you" -msgstr "пытается связаться с вами" +msgstr "контактирует с вами" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid " and asked autoanswer." -msgstr " и ответил автоответчик." +msgstr "и спросил автоматический ответ." -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid "." msgstr "." -#: ../coreapi/linphonecore.c:3139 +#: ../coreapi/linphonecore.c:2865 msgid "Modifying call parameters..." -msgstr "Изменение параметров вызова..." +msgstr "Изменение параметров звонка..." -#: ../coreapi/linphonecore.c:3469 +#: ../coreapi/linphonecore.c:3194 msgid "Connected." msgstr "Соединён." -#: ../coreapi/linphonecore.c:3495 +#: ../coreapi/linphonecore.c:3220 msgid "Call aborted" -msgstr "Вызов отменён" +msgstr "Звонок отменён" -#: ../coreapi/linphonecore.c:3685 +#: ../coreapi/linphonecore.c:3412 msgid "Could not pause the call" -msgstr "Не удалось приостановить вызов" +msgstr "Невозможно приостановить звонок" -#: ../coreapi/linphonecore.c:3690 +#: ../coreapi/linphonecore.c:3417 msgid "Pausing the current call..." -msgstr "Приостановление текущего вызова..." +msgstr "Приостановка текущего звонка..." #: ../coreapi/misc.c:425 msgid "Stun lookup in progress..." -msgstr "Идет поиск Stun..." +msgstr "Идет поиск STUN..." #: ../coreapi/misc.c:607 msgid "ICE local candidates gathering in progress..." -msgstr "" +msgstr "Сбор локальных кандидатов ICE в прогрессе..." #: ../coreapi/friend.c:33 msgid "Online" @@ -1970,7 +1893,7 @@ msgstr "Не беспокоить" #: ../coreapi/friend.c:54 msgid "Moved" -msgstr "Отошел" +msgstr "Отошёл" #: ../coreapi/friend.c:57 msgid "Using another messaging service" @@ -1985,211 +1908,183 @@ msgid "Pending" msgstr "В ожидании" #: ../coreapi/friend.c:66 -#, fuzzy msgid "Vacation" -msgstr "Продолжительность" +msgstr "Отдых" #: ../coreapi/friend.c:68 msgid "Unknown-bug" msgstr "Неизвестная ошибка" -#: ../coreapi/proxy.c:279 +#: ../coreapi/proxy.c:314 msgid "" "The sip proxy address you entered is invalid, it must start with \"sip:\" " "followed by a hostname." msgstr "" -"Введеный адрес SIP-прокси является недействительным, он должен выглядеть как " +"Введённый SIP-адрес прокси является недействительным, он должен начинаться с " "\"sip:имя_хоста\"" -#: ../coreapi/proxy.c:285 +#: ../coreapi/proxy.c:320 msgid "" "The sip identity you entered is invalid.\n" "It should look like sip:username@proxydomain, such as sip:alice@example.net" msgstr "" -"Неверные параметры идентификации SIP.\n" -"Они должны выглядеть как sip:username@proxydomain, например such as sip:" +"Неверные параметры для sip идентификации\n" +"Должно выглядеть как sip:имя_пользователя@домен_прокси, как например, sip:" "alice@example.net" -#: ../coreapi/proxy.c:1299 +#: ../coreapi/proxy.c:1369 #, c-format msgid "Could not login as %s" -msgstr "Невозможно зайти как %s" +msgstr "Невозможно зайти как: %s" -#: ../coreapi/callbacks.c:354 +#: ../coreapi/callbacks.c:355 msgid "Remote ringing." -msgstr "Абонент вызывается." +msgstr "Дистанционный звонок." -#: ../coreapi/callbacks.c:370 +#: ../coreapi/callbacks.c:373 msgid "Remote ringing..." -msgstr "Абонент вызывается..." +msgstr "Дистанционный звонок..." -#: ../coreapi/callbacks.c:381 +#: ../coreapi/callbacks.c:384 msgid "Early media." -msgstr "Гудки." +msgstr "Предответное проключение." -#: ../coreapi/callbacks.c:432 +#: ../coreapi/callbacks.c:435 #, c-format msgid "Call with %s is paused." -msgstr "Вызов %s приостановлен." +msgstr "Звонок с %s приостановлен." -#: ../coreapi/callbacks.c:445 +#: ../coreapi/callbacks.c:448 #, c-format msgid "Call answered by %s - on hold." -msgstr "Вызов отвечен %s - в ожидании." +msgstr "На звонок ответил %s - на удержании." -#: ../coreapi/callbacks.c:456 +#: ../coreapi/callbacks.c:459 msgid "Call resumed." -msgstr "Разговор продолжен." +msgstr "Звонок возобновлён." -#: ../coreapi/callbacks.c:461 +#: ../coreapi/callbacks.c:464 #, c-format msgid "Call answered by %s." -msgstr "Вызов отвечен %s." +msgstr "На звонок ответил %s." -#: ../coreapi/callbacks.c:480 -#, fuzzy +#: ../coreapi/callbacks.c:483 msgid "Incompatible, check codecs or security settings..." -msgstr "Несовместимо, проверьте кодеки..." +msgstr "Несовместимость, проверьте кодеки или параметры безопасности..." -#: ../coreapi/callbacks.c:531 -#, fuzzy +#: ../coreapi/callbacks.c:512 msgid "We have been resumed." -msgstr "Наш вызов продолжен..." +msgstr "Мы возобновили." -#: ../coreapi/callbacks.c:541 +#: ../coreapi/callbacks.c:521 msgid "We are paused by other party." -msgstr "" +msgstr "Мы приостановлены другой стороной." -#: ../coreapi/callbacks.c:558 -#, fuzzy +#: ../coreapi/callbacks.c:556 msgid "Call is updated by remote." -msgstr "Вызов обновлён вызываемым абонентом..." +msgstr "Звонок был дистанционно обновлён." -#: ../coreapi/callbacks.c:637 +#: ../coreapi/callbacks.c:658 msgid "Call terminated." msgstr "Звонок прерван." -#: ../coreapi/callbacks.c:666 +#: ../coreapi/callbacks.c:687 msgid "User is busy." msgstr "Пользователь занят." -#: ../coreapi/callbacks.c:667 +#: ../coreapi/callbacks.c:688 msgid "User is temporarily unavailable." msgstr "Пользователь временно недоступен." #. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:669 +#: ../coreapi/callbacks.c:690 msgid "User does not want to be disturbed." -msgstr "Абонент не хочет отвечать." +msgstr "Пользователь не хочет чтобы его беспокоили." -#: ../coreapi/callbacks.c:670 +#: ../coreapi/callbacks.c:691 msgid "Call declined." msgstr "Звонок отклонён." -#: ../coreapi/callbacks.c:685 +#: ../coreapi/callbacks.c:706 msgid "Request timeout." -msgstr "" +msgstr "Таймаут запроса." -#: ../coreapi/callbacks.c:716 +#: ../coreapi/callbacks.c:737 msgid "Redirected" msgstr "Переадресован" -#: ../coreapi/callbacks.c:766 -#, fuzzy +#: ../coreapi/callbacks.c:787 msgid "Incompatible media parameters." -msgstr "Несовместимо, проверьте кодеки..." +msgstr "Несовместимость медиа-параметров." -#: ../coreapi/callbacks.c:777 +#: ../coreapi/callbacks.c:798 msgid "Call failed." -msgstr "Не удалось совершить вызов." +msgstr "Звонок не удался." -#: ../coreapi/callbacks.c:852 +#: ../coreapi/callbacks.c:878 #, c-format msgid "Registration on %s successful." msgstr "Регистрация на %s прошла успешно." -#: ../coreapi/callbacks.c:853 +#: ../coreapi/callbacks.c:879 #, c-format msgid "Unregistration on %s done." msgstr "Отмена регистрации на %s завершена." -#: ../coreapi/callbacks.c:875 +#: ../coreapi/callbacks.c:897 msgid "no response timeout" msgstr "время ожидания истекло" -#: ../coreapi/callbacks.c:878 +#: ../coreapi/callbacks.c:900 #, c-format msgid "Registration on %s failed: %s" msgstr "Регистрация на %s не удалась: %s" -#: ../coreapi/callbacks.c:885 +#: ../coreapi/callbacks.c:907 msgid "Service unavailable, retrying" -msgstr "" +msgstr "Сервис недоступен, повтор" -#: ../coreapi/linphonecall.c:175 +#: ../coreapi/linphonecall.c:177 #, c-format msgid "Authentication token is %s" -msgstr "Аутентификационный токен: %s" +msgstr "Маркер проверки подлинности: %s" -#: ../coreapi/linphonecall.c:2994 +#: ../coreapi/linphonecall.c:2932 #, c-format msgid "You have missed %i call." msgid_plural "You have missed %i calls." -msgstr[0] "У вас пропущен %i звонок." -msgstr[1] "У вас пропущено %i звонка." -msgstr[2] "У вас пропущено %i звонков." - -#~ msgid "No response." -#~ msgstr "Нет ответа." - -#~ msgid "Protocol error." -#~ msgstr "Ошибка протокола." +msgstr[0] "У вас %i пропущенный вызов." +msgstr[1] "У вас %i пропущенных вызова." +msgstr[2] "У вас %i пропущенных вызов." #~ msgid "" -#~ "Could not parse given sip address. A sip url usually looks like sip:" -#~ "user@domain" +#~ "%s\t%s\tQuality: %s\n" +#~ "%s\t%s %s\t" #~ msgstr "" -#~ "Не могу опознать sip адрес. SIP-URL обычно выглядит как sip:" -#~ "username@domainname" - -#~ msgid "" -#~ "Your computer appears to be using ALSA sound drivers.\n" -#~ "This is the best choice. However the pcm oss emulation module\n" -#~ "is missing and linphone needs it. Please execute\n" -#~ "'modprobe snd-pcm-oss' as root to load it." -#~ msgstr "" -#~ "Ваш компьютер использует звуковой драйвер ALSA.\n" -#~ "Это лучший выбор. Однако, модуль эмуляции PCM OSS\n" -#~ "не найден, а он нужен для linphone.\n" -#~ "Пожалуйста, выполните от имени пользователя root команду 'modprobe snd-" -#~ "pcm-oss', чтобы загрузить его." - -#~ msgid "" -#~ "Your computer appears to be using ALSA sound drivers.\n" -#~ "This is the best choice. However the mixer oss emulation module\n" -#~ "is missing and linphone needs it. Please execute\n" -#~ " 'modprobe snd-mixer-oss' as root to load it." -#~ msgstr "" -#~ "Ваш компьютер использует звуковой драйвер ALSA.\n" -#~ "Это лучший выбор. Однако, модуль микшера OSS\n" -#~ "не найден, а он нужен для linphone.\n" -#~ "Пожалуйста, выполните от имени пользователя root команду 'modprobe snd-" -#~ "pcm-oss' чтобы загрузить его." - -#~ msgid "by %s" -#~ msgstr "со стороны: %s" - -#~ msgid "Keypad" -#~ msgstr "Номеронабиратель" +#~ "%s\t%s\tКачество: %s\n" +#~ "%s\t%s %s\t" #~ msgid "Chat with %s" #~ msgstr "Чат с %s" +#~ msgid "" +#~ "Please enter your password for username %s\n" +#~ " at domain %s:" +#~ msgstr "" +#~ "Пожалуйста, введите пароль для пользователя %s\n" +#~ " для домена %s:" + +#~ msgid "by %s" +#~ msgstr "by %s" + +#~ msgid "Min bitrate (kbit/s)" +#~ msgstr "Минимальный битрейт (КБит/сек)" + #~ msgid "Enable video" -#~ msgstr "Включить видео" +#~ msgstr "Разрешить видео" #~ msgid "Enter username, phone number, or full sip address" -#~ msgstr "Введите имя пользователя, номер телефона или полный SIP-адрес" +#~ msgstr "Введите имя пользователя, номер телефона или полный sip адрес" #~ msgid "Lookup:" #~ msgstr "Поиск:" @@ -2197,8 +2092,39 @@ msgstr[2] "У вас пропущено %i звонков." #~ msgid "in" #~ msgstr "в" +#~ msgid "Keypad" +#~ msgstr "Клавиатура" + +#~ msgid "" +#~ "fr: Simon Morlat\n" +#~ "en: Simon Morlat and Delphine Perreau\n" +#~ "it: Alberto Zanoni \n" +#~ "de: Jean-Jacques Sarton \n" +#~ "sv: Daniel Nylander \n" +#~ "es: Jesus Benitez \n" +#~ "ja: YAMAGUCHI YOSHIYA \n" +#~ "pt_BR: Rafael Caesar Lenzi \n" +#~ "pl: Robert Nasiadek \n" +#~ "cs: Petr Pisar \n" +#~ "hu: anonymous\n" +#~ msgstr "" +#~ "fr: Simon Morlat\n" +#~ "en: Simon Morlat and Delphine Perreau\n" +#~ "it: Alberto Zanoni \n" +#~ "de: Jean-Jacques Sarton \n" +#~ "sv: Daniel Nylander \n" +#~ "es: Jesus Benitez \n" +#~ "ja: YAMAGUCHI YOSHIYA \n" +#~ "pt_BR: Rafael Caesar Lenzi \n" +#~ "pl: Robert Nasiadek \n" +#~ "cs: Petr Pisar \n" +#~ "hu: anonymous\n" + #~ msgid "edit" -#~ msgstr "редактировать" +#~ msgstr "править" + +#~ msgid "Behind NAT / Firewall (specify gateway IP below)" +#~ msgstr "За NAT / брандмауэром (указать IP шлюза ниже)" #~ msgid "" #~ "Register to FONICS\n" @@ -2207,870 +2133,114 @@ msgstr[2] "У вас пропущено %i звонков." #~ "Регистрация в \n" #~ "виртуальной сети FONICS!" +#~ msgid "aborted" +#~ msgstr "прервано" + +#~ msgid "completed" +#~ msgstr "завершён" + +#~ msgid "missed" +#~ msgstr "пропущено" + +#~ msgid "" +#~ "%s at %s\n" +#~ "From: %s\n" +#~ "To: %s\n" +#~ "Status: %s\n" +#~ "Duration: %i mn %i sec\n" +#~ msgstr "" +#~ "%s в %s\n" +#~ "От: %s\n" +#~ "Кому: %s\n" +#~ "Статус: %s\n" +#~ "Длительность: %i мин. %i сек.\n" + +#~ msgid "Outgoing call" +#~ msgstr "Исходящий звонок" + +#~ msgid "" +#~ "Could not parse given sip address. A sip url usually looks like sip:" +#~ "user@domain" +#~ msgstr "" +#~ "Не могу опознать sip адрес. Url для sip обычно выглядит как sip:" +#~ "пользователь@домен" + +#~ msgid "" +#~ "Your computer appears to be using ALSA sound drivers.\n" +#~ "This is the best choice. However the pcm oss emulation module\n" +#~ "is missing and linphone needs it. Please execute\n" +#~ "'modprobe snd-pcm-oss' as root to load it." +#~ msgstr "" +#~ "Ваш компьютер использует ALSA звуковые драйвера.\n" +#~ "Это лучший выбор. Однако, pcm oss модуль эмуляции\n" +#~ "не найден, а он нужен для linphone.\n" +#~ "Пожалуйста, выполните от пользователя root команду 'modprobe snd-pcm-oss' " +#~ "чтобы загрузить его." + +#~ msgid "" +#~ "Your computer appears to be using ALSA sound drivers.\n" +#~ "This is the best choice. However the mixer oss emulation module\n" +#~ "is missing and linphone needs it. Please execute\n" +#~ " 'modprobe snd-mixer-oss' as root to load it." +#~ msgstr "" +#~ "Ваш компьютер использует ALSA звуковые драйвера.\n" +#~ "Это лучший выбор. Однако, mixer oss модуль эмуляции\n" +#~ "не найден, а он нужен для linphone.\n" +#~ "Пожалуйста, выполните от пользователя root команду 'modprobe snd-pcm-oss' " +#~ "чтобы загрузить его." + +#~ msgid "Incompatible, check codecs..." +#~ msgstr "Несовместимость, проверьте кодеки..." + #~ msgid "We are being paused..." -#~ msgstr "Мы на паузе..." +#~ msgstr "Мы приостанавливаемся..." + +#~ msgid "We have been resumed..." +#~ msgstr "Мы возобновили..." + +#~ msgid "Call has been updated by remote..." +#~ msgstr "Звонок был дистанционно обновлён..." + +#~ msgid "No response." +#~ msgstr "Нет ответа." + +#~ msgid "Protocol error." +#~ msgstr "Ошибка протокола." #~ msgid "No common codecs" #~ msgstr "Нет общих кодеков" +#~ msgid "Authentication failure" +#~ msgstr "Неудача аутентификации" + #~ msgid "Please choose a username:" -#~ msgstr "Выберите имя пользователя:" +#~ msgstr "Пожалуйста, выберите имя пользователя:" #~ msgid "Checking if '%s' is available..." -#~ msgstr "Проверка доступности '%s'..." +#~ msgstr "Проверка доступности для '%s'" #~ msgid "Please wait..." -#~ msgstr "Ждите..." +#~ msgstr "Пожалуйста, подождите..." #~ msgid "Sorry this username already exists. Please try a new one." -#~ msgstr "Такое имя пользователя уже существует. Попробуйте выбрать другое." +#~ msgstr "" +#~ "Такое имя пользователя уже существует. Пожалуйста, попробуйте с другим " +#~ "именем." #~ msgid "Ok !" -#~ msgstr "Ок!" +#~ msgstr "ОК!" #~ msgid "Communication problem, please try again later." -#~ msgstr "Проблемы со связью, повторите попытку позже." +#~ msgstr "Проблемы со связью, пожалуйста, повторите попытку позже." #~ msgid "Choosing a username" -#~ msgstr "Имя пользователя:" +#~ msgstr "Выбор имени пользователя" #~ msgid "Verifying" #~ msgstr "Проверка" #~ msgid "Creating your account" -#~ msgstr "Создание аккаунта" +#~ msgstr "Создание вашей учётной записи" #~ msgid "Now ready !" -#~ msgstr "Готово !" - -#, fuzzy -#~ msgid "Unmute" -#~ msgstr "Безлимитный" - -#~ msgid "Contact list" -#~ msgstr "Список контактов" - -#, fuzzy -#~ msgid "Audio & video" -#~ msgstr "Аудио и Видео" - -#~ msgid "Audio only" -#~ msgstr "Только Аудио" - -#~ msgid "Duration:" -#~ msgstr "Продолжительность:" - -#, fuzzy -#~ msgid "_Call history" -#~ msgstr "История звонков" - -#~ msgid "_Linphone" -#~ msgstr "_Linphone" - -#~ msgid "gtk-cancel" -#~ msgstr "Отмена" - -#~ msgid "gtk-ok" -#~ msgstr "Ок" - -#~ msgid "Register at startup" -#~ msgstr "Регистрация при запуске" - -#~ msgid "gtk-close" -#~ msgstr "Закрыть" - -#~ msgid "ITU-G.711 alaw encoder" -#~ msgstr "ITU-G.711 alaw кодировщик" - -#~ msgid "ITU-G.711 alaw decoder" -#~ msgstr "ITU-G.711 alaw декодер" - -#~ msgid "Alsa sound source" -#~ msgstr "Источник ALSA" - -#~ msgid "DTMF generator" -#~ msgstr "Генератор DTMF" - -#~ msgid "The GSM full-rate codec" -#~ msgstr "Кодек GSM full-rate" - -#~ msgid "The GSM codec" -#~ msgstr "Кодек GSM" - -#~ msgid "A filter to make conferencing" -#~ msgstr "Фильтр конференций" - -#, fuzzy -#~ msgid "Echo canceller using speex library" -#~ msgstr "Подавление эхо с использование библиотеки speex" - -#~ msgid "A filter that reads from input and copy to its multiple outputs." -#~ msgstr "Фильтр, перенаправляющий входящий поток в несколько потоков вывода." - -#~ msgid "The theora video encoder from xiph.org" -#~ msgstr "Theora видео декодер с xiph.org" - -#~ msgid "The theora video decoder from xiph.org" -#~ msgstr "Theora видео декодер с xiph.org" - -#~ msgid "ITU-G.711 ulaw encoder" -#~ msgstr "ITU-G.711 ulaw кодировщик" - -#~ msgid "ITU-G.711 ulaw decoder" -#~ msgstr "ITU-G.711 ulaw декодер" - -#~ msgid "A H.263 decoder using ffmpeg library" -#~ msgstr "H.263 декодер ( использует ffmpeg )" - -#~ msgid "A MPEG4 decoder using ffmpeg library" -#~ msgstr "MPEG4 декодер ( использует ffmpeg )" - -#, fuzzy -#~ msgid "A RTP/JPEG decoder using ffmpeg library" -#~ msgstr "MJPEG декодер ( использует ffmpeg )" - -#~ msgid "A MJPEG decoder using ffmpeg library" -#~ msgstr "MJPEG декодер ( использует ffmpeg )" - -#~ msgid "A snow decoder using ffmpeg library" -#~ msgstr "snow декодер ( использует ffmpeg )" - -#~ msgid "A video H.263 encoder using ffmpeg library." -#~ msgstr "H.263 видео-кодировщик ( использует ffmpeg )" - -#~ msgid "" -#~ "A video H.263 encoder using ffmpeg library. It is compliant with old " -#~ "RFC2190 spec." -#~ msgstr "H.263 видео-кодировщик ( использует ffmpeg ). Совместим с RFC2190" - -#~ msgid "A video MPEG4 encoder using ffmpeg library." -#~ msgstr "MPEG4 видео-кодировщик ( использует ffmpeg )." - -#~ msgid "A video snow encoder using ffmpeg library." -#~ msgstr "snow видео-кодировщик ( использует ffmpeg )." - -#, fuzzy -#~ msgid "A RTP/MJPEG encoder using ffmpeg library." -#~ msgstr "MJPEG декодер ( использует ffmpeg )" - -#~ msgid "" -#~ "A video H.263 encoder using ffmpeg library, compliant with old RFC2190 " -#~ "spec." -#~ msgstr "H.263 видео-кодировщик ( использует ffmpeg ). Совместим с RFC2190" - -#, fuzzy -#~ msgid "A MJPEG encoder using ffmpeg library." -#~ msgstr "MJPEG декодер ( использует ffmpeg )" - -#, fuzzy -#~ msgid "Inter ticker communication filter." -#~ msgstr "Ошибка связи с сервером" - -#~ msgid "" -#~ "Your machine appears to be connected to an IPv6 network. By default " -#~ "linphone always uses IPv4. Please update your configuration if you want " -#~ "to use IPv6" -#~ msgstr "" -#~ "Ваш компьютер подключен по IPv6. Linphone по умолчанию использует IPv4. " -#~ "Пожалуйста, обновите настройки если хотите использовать IPv6." - -#, fuzzy -#~ msgid "Show debug messages" -#~ msgstr "Показать окно ошибок" - -#~ msgid "Start call" -#~ msgstr "Вызов" - -#~ msgid "_Modes" -#~ msgstr "_Режимы" - -#~ msgid "Created by Simon Morlat\n" -#~ msgstr "Создан Simon Morlat\n" - -#~ msgid "Accept" -#~ msgstr "Принять" - -#~ msgid "Incoming call from" -#~ msgstr "Входящий вызов от" - -#~ msgid "Linphone - Incoming call" -#~ msgstr "Linphone - Входящий вызов" - -#~ msgid "default soundcard\n" -#~ msgstr "звуковая карта по умолчанию\n" - -#~ msgid "" -#~ "Remote end seems to have disconnected, the call is going to be closed." -#~ msgstr "Удалённый узел отключился, звонок завершён." - -#~ msgid "Sorry, having multiple simultaneous calls is not supported yet !" -#~ msgstr "Одновременные вызовы пока не поддерживается!" - -#~ msgid "gtk-go-down" -#~ msgstr "Вниз" - -#~ msgid "gtk-go-up" -#~ msgstr "Вверх" - -#~ msgid "gtk-media-play" -#~ msgstr "Проиграть" - -#~ msgid "Could not reach destination." -#~ msgstr "Невозможно соединиться." - -#~ msgid "Request Cancelled." -#~ msgstr "Запрос отменён." - -#~ msgid "Bad request" -#~ msgstr "Неверный запрос" - -#~ msgid "User cannot be found at given address." -#~ msgstr "Пользователь не может быть найден." - -#~ msgid "Remote user cannot support any of proposed codecs." -#~ msgstr "" -#~ "Удалённый пользователь не поддерживает ни одного из предложенных кодеков." - -#~ msgid "Timeout." -#~ msgstr "Таймаут." - -#~ msgid "Remote host was found but refused connection." -#~ msgstr "Удалённый узел был найден, но отказал в соединении." - -#~ msgid "" -#~ "User is not reachable at the moment but he invites you\n" -#~ "to contact him using the following alternate resource:" -#~ msgstr "" -#~ "Пользователь не доступен в данный момент, но\n" -#~ "приглашает Вас пообщаться на альтернативном ресурсе:" - -#~ msgid "Digits" -#~ msgstr "Цифры" - -#~ msgid "Main view" -#~ msgstr "Главное окно" - -#~ msgid "No nat/firewall address supplied !" -#~ msgstr "NAT/firewall адрес не установлен !" - -#~ msgid "Invalid nat address '%s' : %s" -#~ msgstr "Неверный NAT адрес '%s' : '%s'" - -#~ msgid "Gone" -#~ msgstr "Ушёл" - -#~ msgid "Waiting for Approval" -#~ msgstr "Ожидание утверждения" - -#~ msgid "Be Right Back" -#~ msgstr "Скоро вернусь" - -#~ msgid "On The Phone" -#~ msgstr "На телефоне" - -#~ msgid "Out To Lunch" -#~ msgstr "На обеде" - -#~ msgid "Closed" -#~ msgstr "Закрыто" - -#~ msgid "Unknown" -#~ msgstr "Неизвестно" - -#~ msgid "gtk-connect" -#~ msgstr "Соединить" - -#~ msgid "gtk-find" -#~ msgstr "Найти" - -#~ msgid "_View" -#~ msgstr "_Вид" - -#~ msgid "gtk-about" -#~ msgstr "О программе" - -#~ msgid "gtk-help" -#~ msgstr "Помощь" - -#~ msgid "gtk-preferences" -#~ msgstr "Параметры" - -#~ msgid "" -#~ "Show All\n" -#~ "Show Online" -#~ msgstr "" -#~ "Показать все\n" -#~ "Показать Online" - -#~ msgid "Display filters" -#~ msgstr "Показать фильтры" - -#~ msgid "I'm not behing a firewall" -#~ msgstr "Я не за firewall" - -#~ msgid "I'm behind a firewall, use supplied public IP address" -#~ msgstr "Я за firewall, использовать доступный IP адрес" - -#~ msgid "Use the supplied stun server above and do as best as possible" -#~ msgstr "Использовать доступный Stun сервер и делать так хорошо как возможно" - -#~ msgid "Go" -#~ msgstr "Старт" - -#~ msgid "Address book" -#~ msgstr "Адресная книга" - -#~ msgid "Shows calls" -#~ msgstr "Показать звонки" - -#~ msgid "Exit" -#~ msgstr "Выход" - -#~ msgid "Shows the address book" -#~ msgstr "Показать адресную книгу" - -#~ msgid "..." -#~ msgstr "..." - -#~ msgid "Proxy to use:" -#~ msgstr "Какой узел использовать:" - -#~ msgid "" -#~ "Hangup\n" -#~ "or refuse" -#~ msgstr "" -#~ "Прервать\n" -#~ "или отказать" - -#~ msgid "Or chat !" -#~ msgstr "Или Чат ! " - -#~ msgid "Show more..." -#~ msgstr "Показать больше..." - -#~ msgid "Playback level:" -#~ msgstr "Уровень воспроизведения:" - -#~ msgid "Recording level:" -#~ msgstr "Уровень записи:" - -#~ msgid "Ring level:" -#~ msgstr "Уровень звонка:" - -#~ msgid "Controls" -#~ msgstr "Управление" - -#~ msgid "Reachable" -#~ msgstr "Доступен" - -#~ msgid "Busy, I'll be back in " -#~ msgstr "Занят, я вернусь через " - -#~ msgid "The other party will be informed that you'll be back in X minutes" -#~ msgstr "Другая часть информирует, что Вы вернётесь через X минут" - -#~ msgid "mn" -#~ msgstr "мн" - -#~ msgid "Moved temporarily" -#~ msgstr "Временно переехал" - -#~ msgid "Alternative service" -#~ msgstr "Альтернативный сервис" - -#~ msgid "URL:" -#~ msgstr "URL:" - -#~ msgid "Presence" -#~ msgstr "Статус" - -#~ msgid "Press digits to send DTMFs." -#~ msgstr "Введите цифры, чтоб отправить DTMF." - -#~ msgid "" -#~ " 3\n" -#~ "def" -#~ msgstr "" -#~ " 3\n" -#~ "где" - -#~ msgid "" -#~ " 2\n" -#~ "abc" -#~ msgstr "" -#~ " 2\n" -#~ "абв" - -#~ msgid "" -#~ " 4\n" -#~ "ghi" -#~ msgstr "" -#~ " 4\n" -#~ "жзи" - -#~ msgid "" -#~ " 5\n" -#~ "jkl" -#~ msgstr "" -#~ " 5\n" -#~ "клм" - -#~ msgid "" -#~ " 6\n" -#~ "mno" -#~ msgstr "" -#~ " 6\n" -#~ "ноп" - -#~ msgid "" -#~ " 7\n" -#~ "pqrs" -#~ msgstr "" -#~ " 7\n" -#~ "рст" - -#~ msgid "" -#~ " 8\n" -#~ "tuv" -#~ msgstr "" -#~ " 8\n" -#~ "уфх" - -#~ msgid "" -#~ " 9\n" -#~ "wxyz" -#~ msgstr "" -#~ " 9\n" -#~ "шюя" - -#~ msgid "DTMF" -#~ msgstr "DTMF" - -#~ msgid "My online friends" -#~ msgstr "Мои друзья онлайн:" - -#~ msgid "" -#~ "C: 2001\n" -#~ "Made in Old Europe" -#~ msgstr "" -#~ "C: 2001\n" -#~ "Сделано в старой Европе" - -#~ msgid "" -#~ "Linphone is a web-phone.\n" -#~ "It is compatible with SIP and RTP protocols." -#~ msgstr "" -#~ "Linphone - это интернет телефон.\n" -#~ "Он совместим с SIP и RTP протоколами." - -#~ msgid "http://www.linphone.org" -#~ msgstr "http://www.linphone.org/" - -#~ msgid "Use IPv6 network (if available)" -#~ msgstr "Использовать IPv6 сеть (если доступно)" - -# msgstr "Teilnehmer zur Zeit nicht ansprechbar." -#~ msgid "" -#~ "Toggle this if you are on an ipv6 network and you wish linphone to use it." -#~ msgstr "Отметьте, если Вы в сети с ipv6 и будите использовать linphone." - -#~ msgid "Global" -#~ msgstr "Основные" - -#~ msgid "" -#~ "These options is only for users in a private network, behind a gateway. " -#~ "If you are not in this situation, then leave this empty." -#~ msgstr "" -#~ "Эта опция используется в частных сетях, за шлюзом. Если вы не в этой " -#~ "ситуации, просто оставьте пустой." - -#~ msgid "No firewall" -#~ msgstr "Нет firewall'a" - -#~ msgid "Use this STUN server to guess firewall address :" -#~ msgstr "Используйте этот STUN сервер чтоб определить адрес firewall :" - -#~ msgid "Specify firewall address manually:" -#~ msgstr "Определить адрес Firewall вручную:" - -#~ msgid "NAT traversal options (experimental)" -#~ msgstr "NAT опции (экспериментально)" - -#~ msgid "Number of buffered miliseconds (jitter compensation):" -#~ msgstr "Число милисекунд для буферизации (компенсация дрожания):" - -#~ msgid "RTP port used for audio:" -#~ msgstr "RTP порт для аудио:" - -#~ msgid "Use SIP INFO message instead of RTP rfc2833 for DTMF transmitting" -#~ msgstr "" -#~ "Используйте SIP INFO сообщения вместо RTP rfc2833 для DTMF препровождения" - -#~ msgid "RTP-RFC2833 is the recommended way." -#~ msgstr "RTP-RFC2833 рекомендуемый." - -#~ msgid "Other" -#~ msgstr "Другое" - -#~ msgid "micro" -#~ msgstr "Микрофон" - -#~ msgid "Enable echo-canceler (cancels the echo heard by the remote party)" -#~ msgstr "" -#~ "Включить подавление эхо (подавляет эхо слышимое с удалённого устройства)" - -#~ msgid "Choose file" -#~ msgstr "Выберите файл" - -#~ msgid "Listen" -#~ msgstr "Слушать" - -#~ msgid "Sound device" -#~ msgstr "Устройство звука" - -#~ msgid "Run sip user agent on port:" -#~ msgstr "Запустить \"user agent\" на порту:" - -#~ msgid "It is strongly recommended to use port 5060." -#~ msgstr "Рекомендуется использовать порт 5060." - -#~ msgid "@" -#~ msgstr "@" - -#~ msgid "Identity" -#~ msgstr "Личность" - -#~ msgid "Add proxy/registrar" -#~ msgstr "Добавить прокси/регистратора" - -#~ msgid "Remote services" -#~ msgstr "Удалённые сервисы" - -#~ msgid "Clear all stored authentication information (username,password...)" -#~ msgstr "Удалить всю информацию аунтефикации (логин, пароль...)" - -#~ msgid "List of audio codecs, in order of preference:" -#~ msgstr "Список аудио кодеков в приоритетном порядке:" - -#~ msgid "" -#~ "Note: Codecs in red are not usable regarding to your connection type to " -#~ "the internet." -#~ msgstr "" -#~ "Заметка: Кодеки отмеченные красным не подходят для вашего соединения в " -#~ "Internet." - -#~ msgid "No information availlable" -#~ msgstr "Информация недоступна" - -#~ msgid "Codec information" -#~ msgstr "Информация о кодеке" - -#~ msgid "Address Book" -#~ msgstr "Адресная книга" - -#~ msgid "Select" -#~ msgstr "Выбор" - -#~ msgid "" -#~ "User is not reachable at the moment but he invites you to contact him " -#~ "using the following alternate ressource:" -#~ msgstr "" -#~ "Пользователь не доступен в данный момент, но приглашает пообщаться на " -#~ "альтернативном ресурсе:" - -#~ msgid "None." -#~ msgstr "Нет." - -#~ msgid "Send registration:" -#~ msgstr "Отправить регистрацию:" - -#~ msgid "Name:" -#~ msgstr "Имя:" - -#~ msgid "Subscribe policy:" -#~ msgstr "Правило подписки:" - -#~ msgid "Send subscription (see person's online status)" -#~ msgstr "Отправить подписку (смотреть статус персоны в сети)" - -#~ msgid "New incoming subscription" -#~ msgstr "Подтверждение новой подписки" - -#~ msgid "You have received a new subscription..." -#~ msgstr "Вы получили новое подтверждение..." - -#~ msgid "Refuse" -#~ msgstr "Отказать" - -#~ msgid "Authentication required for realm" -#~ msgstr "Регистрация для" - -#~ msgid "userid:" -#~ msgstr "ID пользователя:" - -#~ msgid "Linphone - Call history" -#~ msgstr "Linphone - История звонков" - -#~ msgid "Text:" -#~ msgstr "Текст" - -#~ msgid "The caller asks for resource reservation. Do you agree ?" -#~ msgstr "" -#~ "Вызывающий абонент спрашивает о резервировании ресурса. Вы согласны ?" - -#~ msgid "" -#~ "The caller doesn't use resource reservation. \t\t\t\t\tDo you wish to " -#~ "continue anyway ?" -#~ msgstr "" -#~ "Вызывающий не использует резервирование ресурса. \t\t\t\t\tВы всё равно " -#~ "желаете продолжить?" - -#~ msgid "linphone - receiving call from %s" -#~ msgstr "Linphone - принял звонок от %s" - -#~ msgid "" -#~ "You have received a subscription from %s.This means that this person " -#~ "wishes to be notified of your presence information (online, busy, " -#~ "away...).\n" -#~ "Do you agree ?" -#~ msgstr "" -#~ "Вы получили запрос на подключение от %s. Это значит что этот человек " -#~ "хочет знать ваш статус (онлайн, занят, отошёл...).\n" -#~ "Вы согласны ?" - -#~ msgid "Authentication required for realm %s" -#~ msgstr "Регистрация для %s" - -#~ msgid "Wait" -#~ msgstr "Подождать" - -#~ msgid "Deny" -#~ msgstr "Отказать" - -#~ msgid "Bad sip address: a sip address looks like sip:user@domain" -#~ msgstr "Неправильный sip адрес, он выглядит как: " - -#~ msgid "Stun lookup done..." -#~ msgstr "Поиск Stun завершён..." - -#~ msgid "enter sip uri here" -#~ msgstr "Sip URI eingeben" - -#~ msgid "User manual" -#~ msgstr "Anwender-Handbuch" - -#~ msgid "Ring sound selection" -#~ msgstr "Klingelton ausw�len" - -#~ msgid "Communication ended." -#~ msgstr "Kommunikation beendet." - -#, fuzzy -#~ msgid "Firewall 's external ip address (in dot notations):" -#~ msgstr "IP-Adresse des Firewall (in Punktnotation)" - -#~ msgid "28k modem" -#~ msgstr "28K Modem" - -#~ msgid "56k modem" -#~ msgstr "56K Modem" - -#~ msgid "64k modem (numeris)" -#~ msgstr "64K Modem (ISDN)" - -#~ msgid "ADSL or Cable modem" -#~ msgstr "ADSL oder Kabel-Modem" - -#~ msgid "Ethernet or equivalent" -#~ msgstr "Ethernet oder �uivalent" - -#~ msgid "Connection type:" -#~ msgstr "Verbindungstyp:" - -#, fuzzy -#~ msgid "" -#~ "Linphone could not open audio device %s. Check if your sound card is " -#~ "fully configured and working." -#~ msgstr "" -#~ "Linphone kann das Soundger� nicht �fnen. Prfen Sie nach, ob dieSoundkarte " -#~ "vollst�dig konfiguriert und funktionsf�ig ist." - -#~ msgid "Type here the sip address of the person you want to call." -#~ msgstr "" -#~ "Geben Sie die Sip-Adresse des Anwenders, den Sie anrufen m�hten, hier ein." - -#~ msgid "" -#~ "Release or\n" -#~ "Refuse" -#~ msgstr "" -#~ "Auflegen oder\n" -#~ "Abweisen" - -#~ msgid "%s. Retry after %i minute(s)." -#~ msgstr "%s. In %i Minuten wieder versuchen." - -#~ msgid "Timeout..." -#~ msgstr "Zeitberschreitung..." - -#~ msgid "Toggle this if you want to be registered on a remote server." -#~ msgstr "" -#~ "Bitte ankreuzen, wenn Sie auf einem Sip-Server registriert werden wollen." - -#~ msgid "Address of record:" -#~ msgstr "Adresse des Eintrags:" - -#~ msgid "" -#~ "The password used for registration. On some servers it is not necessary" -#~ msgstr "" -#~ "Passwort fr die Registrierung. Bei manchen Servern nicht erforderlich." - -#~ msgid "Use this registrar server as outbound proxy." -#~ msgstr "Verwenden Sie diesen Registrarserver als externen proxy." - -#~ msgid "sip address:" -#~ msgstr "SIP-Adresse:" - -#~ msgid "Modify" -#~ msgstr "�dern" - -#~ msgid "" -#~ "You are currently using the i810_audio driver.\n" -#~ "This driver is buggy and so does not work with Linphone.\n" -#~ "We suggest that you replace it by its equivalent ALSA driver,\n" -#~ "either with packages from your distribution, or by downloading\n" -#~ "ALSA drivers at http://www.alsa-project.org." -#~ msgstr "" -#~ "Sie verwenden zur Zeit den i810_audio Treiber.\n" -#~ "Diese Treiber ist fehlerhaft und funktioniert nicht mit Linphone\n" -#~ "Wir empfehlen, den Treiber entweder durch das ALSA-Treiber-Paket von " -#~ "ihrer Distribution\n" -#~ "zu ersetzen oder die gewnschten ALSA-Treiber von http://www.alsa-project." -#~ "org\n" -#~ "zu beziehen und zu installieren" - -#~ msgid "Unregistration successfull." -#~ msgstr "Abmeldung erfolgreich." - -#~ msgid "Select network interface to use:" -#~ msgstr "Netzwerkschnittstelle w�len:" - -#~ msgid "Network interface properties" -#~ msgstr "Eigenschaften der Netzwerkschnittstelle" - -#~ msgid "RTP" -#~ msgstr "RTP" - -#~ msgid "C: 2001" -#~ msgstr "April 2001" - -#~ msgid "Threads not supported by glib. Upgrade your glib.\n" -#~ msgstr "" -#~ "Threads werden von glib nicht untersttzt. Bitte aktualisieren Sie Ihre " -#~ "glib.\n" - -#~ msgid "Run linphone as a gnome-applet." -#~ msgstr "Linphone als gnome-Applet ausfhren." - -#~ msgid "Run linphone as a daemon (for use without gnome)." -#~ msgstr "Linphone als daemon ausfhren (Verwendung ohne Gnome)." - -#~ msgid "" -#~ "Cannot find network previously used interface %s.\n" -#~ "If your computer is temporary connected to the internet, please connect " -#~ "and then run linphone.\n" -#~ "If you want to change your default network interface, go to the " -#~ "parameters 'box." -#~ msgstr "" -#~ "Linphone konnte die zuvor verwendete Netzwerkschnittstelle %s nicht " -#~ "finden.\n" -#~ "Wenn linphone nur tempor� am Internet angeschlossen ist, stellen Sie eine " -#~ "Verbindung her und rufen Sie linphone erneut auf.\n" -#~ "Wenn Sie die vorgegebene Netzwerkschnittstelle �dern wollen, w�len Sie " -#~ "bitte \"Einstellungen\"." - -#~ msgid "" -#~ "Linphone cannot open the audio device.\n" -#~ "It may be caused by other programs using it.\n" -#~ "Do you want linphone to kill these programs (esd or artsd) ?" -#~ msgstr "" -#~ "Linphone kann die Soundschnittstelle nicht �fnen.\n" -#~ "Dies kann durch andere Applikationen verursacht sein.\n" -#~ "M�hten sie diese Programme (esd oder artsd) beenden?" - -#~ msgid "Use it as a:" -#~ msgstr "Verwenden als:" - -#~ msgid "Outbound proxy" -#~ msgstr "Ausgehender Proxy-Server" - -#~ msgid "" -#~ "Toggle this button if the registrar must be used to proxy calls through a " -#~ "firewall." -#~ msgstr "" -#~ "Verwenden Sie diesen Knopf, falls der Registrar zum Tunneln durch einen " -#~ "Firewall verwendet werden mu�" - -#~ msgid "kbit/s" -#~ msgstr "Kbits/s" - -#~ msgid "OSS" -#~ msgstr "OSS" - -#~ msgid "ALSA" -#~ msgstr "ALSA" - -#~ msgid "Automatically kill applications using soundcard when needed" -#~ msgstr "Applikationen die die Soundkarte verwenden, automatisch beenden." - -#~ msgid "" -#~ "Your computer is connected to several networks. Check in the global " -#~ "parameters if Linphone uses the one that you want." -#~ msgstr "" -#~ "Ihr Rechner ist an mehere Netze angeschlossen. Stellen Sie sicher, da�in " -#~ "den Globalen Parametern die richtige Schnittstelle selektiert ist." - -#~ msgid "" -#~ "Linphone failed to open the sound device. See the README file included in " -#~ "the distribution for details." -#~ msgstr "" -#~ "Linphone konnte die Soundschnittstelle nicht �fnen. Weitere Informationen " -#~ "finden Sie in der README-Datei (enthalten in der Distribution)." - -#~ msgid "Interface not found." -#~ msgstr "Schnittstelle nicht gefunden." - -#~ msgid "Warning" -#~ msgstr "Warnung" - -#~ msgid "" -#~ "Linphone cannot open the sound device. It may be caused by other programs " -#~ "using it. Do you want linphone to kill these programs (esd or artsd) ?" -#~ msgstr "" -#~ "Linphone kann die Soundschnittstelle nicht �fnen. Dies kann durch andere " -#~ "Applikationen verursacht sein. M�hten sie diese Programme (esd oder " -#~ "artsd) beenden?" - -#~ msgid "Linphone shutdowns..." -#~ msgstr "Linphone Ende..." - -#~ msgid "" -#~ "Please, wait a few seconds untils linphone unregisters your sip addess " -#~ "from registrar server..." -#~ msgstr "Bitte einige Sekunden warten, bis Sip-Adresse ausgetragen ist." - -#~ msgid "Bad formuled sip address." -#~ msgstr "SIP-Adresse fehlerhaft." - -#~ msgid "Couldn't create pixmap from file: %s" -#~ msgstr "Konnte Pixmap nicht aus Datei %s erzeugen." - -#~ msgid "" -#~ "Linphone did not detect any valid network interface. If you use a " -#~ "temporary internet connection, please connect and then run linphone again." -#~ msgstr "" -#~ "Linphone konnte keine Netzwerkschnittstelle finden. Wenn Sie nur eine " -#~ "tempor�e Internetverbindung haben, bitte erneut eine Internetverbindung " -#~ "herstellen und linphone nochmals starten." - -#~ msgid "List of network interfaces on your system." -#~ msgstr "Vorhandene Netzwerkschnittstellen ihres Systems" +#~ msgstr "Готово!" diff --git a/po/sr.po b/po/sr.po index ed088ef14..2ec83343c 100644 --- a/po/sr.po +++ b/po/sr.po @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: linphone 0.7.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-01 21:24+0200\n" +"POT-Creation-Date: 2014-09-15 09:24+0200\n" "PO-Revision-Date: 2013-02-11 19:03+0200\n" "Last-Translator: Мирослав Николић \n" "Language-Team: Serbian \n" @@ -16,12 +16,12 @@ msgstr "" "Plural-Forms: nplurals=4; plural=n==1? 3 : n%10==1 && n%100!=11 ? 0 : n" "%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" -#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:973 +#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:974 #, c-format msgid "Call %s" msgstr "Позови „%s“" -#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:974 +#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:975 #, c-format msgid "Send text to %s" msgstr "Пошаљи текст за %s" @@ -31,26 +31,26 @@ msgstr "Пошаљи текст за %s" msgid "Recent calls (%i)" msgstr "У позиву" -#: ../gtk/calllogs.c:312 +#: ../gtk/calllogs.c:314 msgid "n/a" msgstr "н/д" -#: ../gtk/calllogs.c:315 +#: ../gtk/calllogs.c:317 #, fuzzy msgid "Aborted" msgstr "прекинути" -#: ../gtk/calllogs.c:318 +#: ../gtk/calllogs.c:320 #, fuzzy msgid "Missed" msgstr "пропуштени" -#: ../gtk/calllogs.c:321 +#: ../gtk/calllogs.c:323 #, fuzzy msgid "Declined" msgstr "Одбиј" -#: ../gtk/calllogs.c:327 +#: ../gtk/calllogs.c:329 #, c-format msgid "%i minute" msgid_plural "%i minutes" @@ -59,7 +59,7 @@ msgstr[1] "%i минута" msgstr[2] "%i минута" msgstr[3] "Један минут" -#: ../gtk/calllogs.c:330 +#: ../gtk/calllogs.c:332 #, c-format msgid "%i second" msgid_plural "%i seconds" @@ -68,14 +68,14 @@ msgstr[1] "%i секунде" msgstr[2] "%i секунде" msgstr[3] "Једна секунда" -#: ../gtk/calllogs.c:333 ../gtk/calllogs.c:339 +#: ../gtk/calllogs.c:335 ../gtk/calllogs.c:341 #, fuzzy, c-format msgid "%s\t%s" msgstr "" "%s\t%s\tКвалитет: %s\n" "%s\t%s %s\t" -#: ../gtk/calllogs.c:335 +#: ../gtk/calllogs.c:337 #, fuzzy, c-format msgid "" "%s\tQuality: %s\n" @@ -84,7 +84,7 @@ msgstr "" "%s\t%s\tКвалитет: %s\n" "%s\t%s %s\t" -#: ../gtk/calllogs.c:341 +#: ../gtk/calllogs.c:343 #, fuzzy, c-format msgid "" "%s\t\n" @@ -106,7 +106,7 @@ msgstr "Ја" msgid "Couldn't find pixmap file: %s" msgstr "Не могу да пронађем датотеку сличице: %s" -#: ../gtk/chat.c:363 ../gtk/friendlist.c:923 +#: ../gtk/chat.c:364 ../gtk/friendlist.c:924 msgid "Invalid sip contact !" msgstr "Неисправан сип контакт !" @@ -157,7 +157,7 @@ msgstr "Помоћник подешавања налога" msgid "Call with %s" msgstr "Позив са корисником %s" -#: ../gtk/main.c:1171 +#: ../gtk/main.c:1183 #, c-format msgid "" "%s would like to add you to his contact list.\n" @@ -170,7 +170,7 @@ msgstr "" "на ваш списак пријатеља ?\n" "Ако одговорите са не, ова особа ће привремено бити стављена на црни списак." -#: ../gtk/main.c:1248 +#: ../gtk/main.c:1260 #, fuzzy, c-format msgid "" "Please enter your password for username %s\n" @@ -179,59 +179,59 @@ msgstr "" "Унесите вашу лозинку за корисничко име %s\n" " на домену %s:" -#: ../gtk/main.c:1364 +#: ../gtk/main.c:1376 msgid "Call error" msgstr "Грешка позива" -#: ../gtk/main.c:1367 ../coreapi/linphonecore.c:3515 +#: ../gtk/main.c:1379 ../coreapi/linphonecore.c:3240 msgid "Call ended" msgstr "Позив је завршен" -#: ../gtk/main.c:1370 ../coreapi/linphonecore.c:254 +#: ../gtk/main.c:1382 msgid "Incoming call" msgstr "Долазни позив" -#: ../gtk/main.c:1372 ../gtk/incall_view.c:513 ../gtk/main.ui.h:5 +#: ../gtk/main.c:1384 ../gtk/incall_view.c:522 ../gtk/main.ui.h:5 msgid "Answer" msgstr "Јави се" -#: ../gtk/main.c:1374 ../gtk/main.ui.h:6 +#: ../gtk/main.c:1386 ../gtk/main.ui.h:6 msgid "Decline" msgstr "Одбиј" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 msgid "Call paused" msgstr "Позив је заустављен" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy, c-format msgid "by %s" msgstr "Кодеци" -#: ../gtk/main.c:1447 +#: ../gtk/main.c:1459 #, c-format msgid "%s proposed to start video. Do you accept ?" msgstr "" -#: ../gtk/main.c:1609 +#: ../gtk/main.c:1621 msgid "Website link" msgstr "Веза веб сајта" -#: ../gtk/main.c:1658 +#: ../gtk/main.c:1670 msgid "Linphone - a video internet phone" msgstr "Линфон — интернет телефон са снимком" -#: ../gtk/main.c:1750 +#: ../gtk/main.c:1762 #, c-format msgid "%s (Default)" msgstr "%s (основно)" -#: ../gtk/main.c:2086 ../coreapi/callbacks.c:927 +#: ../gtk/main.c:2099 ../coreapi/callbacks.c:949 #, c-format msgid "We are transferred to %s" msgstr "Преселили смо се на %s" -#: ../gtk/main.c:2096 +#: ../gtk/main.c:2109 msgid "" "No sound cards have been detected on this computer.\n" "You won't be able to send or receive audio calls." @@ -239,7 +239,7 @@ msgstr "" "Ниједна звучна картица није откривен ана овом рачунару.\n" "Нећете бити у могућности да шаљете или да примате звучне позиве." -#: ../gtk/main.c:2237 +#: ../gtk/main.c:2250 msgid "A free SIP video-phone" msgstr "Слободан СИП телефон са снимком" @@ -251,7 +251,7 @@ msgstr "Додајте у адресар" msgid "Presence status" msgstr "Стање присуства" -#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:550 ../gtk/contact.ui.h:1 +#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:552 ../gtk/contact.ui.h:1 msgid "Name" msgstr "Име" @@ -268,142 +268,142 @@ msgstr "" msgid "Search in %s directory" msgstr "Тражи у директоријуму „%s“" -#: ../gtk/friendlist.c:975 +#: ../gtk/friendlist.c:976 #, c-format msgid "Edit contact '%s'" msgstr "Уредите контакт „%s“" -#: ../gtk/friendlist.c:976 +#: ../gtk/friendlist.c:977 #, c-format msgid "Delete contact '%s'" msgstr "Обришите контакт „%s“" -#: ../gtk/friendlist.c:977 +#: ../gtk/friendlist.c:978 #, fuzzy, c-format msgid "Delete chat history of '%s'" msgstr "Обришите контакт „%s“" -#: ../gtk/friendlist.c:1028 +#: ../gtk/friendlist.c:1029 #, c-format msgid "Add new contact from %s directory" msgstr "Додајте нови контакт из директоријума „%s“" -#: ../gtk/propertybox.c:556 +#: ../gtk/propertybox.c:558 msgid "Rate (Hz)" msgstr "Проток (Hz)" -#: ../gtk/propertybox.c:562 +#: ../gtk/propertybox.c:564 msgid "Status" msgstr "Стање" -#: ../gtk/propertybox.c:568 +#: ../gtk/propertybox.c:570 #, fuzzy msgid "IP Bitrate (kbit/s)" msgstr "Најмањи проток бита (kbit/s)" -#: ../gtk/propertybox.c:575 +#: ../gtk/propertybox.c:577 msgid "Parameters" msgstr "Параметри" -#: ../gtk/propertybox.c:618 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:763 msgid "Enabled" msgstr "Укључено" -#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:622 ../gtk/propertybox.c:763 msgid "Disabled" msgstr "Искључено" -#: ../gtk/propertybox.c:807 +#: ../gtk/propertybox.c:809 msgid "Account" msgstr "Налог" -#: ../gtk/propertybox.c:1061 +#: ../gtk/propertybox.c:1063 msgid "English" msgstr "Енглески" -#: ../gtk/propertybox.c:1062 +#: ../gtk/propertybox.c:1064 msgid "French" msgstr "Француски" -#: ../gtk/propertybox.c:1063 +#: ../gtk/propertybox.c:1065 msgid "Swedish" msgstr "Шведски" -#: ../gtk/propertybox.c:1064 +#: ../gtk/propertybox.c:1066 msgid "Italian" msgstr "Италијански" -#: ../gtk/propertybox.c:1065 +#: ../gtk/propertybox.c:1067 msgid "Spanish" msgstr "Шпански" -#: ../gtk/propertybox.c:1066 +#: ../gtk/propertybox.c:1068 msgid "Brazilian Portugese" msgstr "Бразилски португалски" -#: ../gtk/propertybox.c:1067 +#: ../gtk/propertybox.c:1069 msgid "Polish" msgstr "Пољски" -#: ../gtk/propertybox.c:1068 +#: ../gtk/propertybox.c:1070 msgid "German" msgstr "Немачки" -#: ../gtk/propertybox.c:1069 +#: ../gtk/propertybox.c:1071 msgid "Russian" msgstr "Руски" -#: ../gtk/propertybox.c:1070 +#: ../gtk/propertybox.c:1072 msgid "Japanese" msgstr "Јапански" -#: ../gtk/propertybox.c:1071 +#: ../gtk/propertybox.c:1073 msgid "Dutch" msgstr "Холандски" -#: ../gtk/propertybox.c:1072 +#: ../gtk/propertybox.c:1074 msgid "Hungarian" msgstr "Мађарски" -#: ../gtk/propertybox.c:1073 +#: ../gtk/propertybox.c:1075 msgid "Czech" msgstr "Чешки" -#: ../gtk/propertybox.c:1074 +#: ../gtk/propertybox.c:1076 msgid "Chinese" msgstr "Кинески" -#: ../gtk/propertybox.c:1075 +#: ../gtk/propertybox.c:1077 msgid "Traditional Chinese" msgstr "Традиционални кинески" -#: ../gtk/propertybox.c:1076 +#: ../gtk/propertybox.c:1078 msgid "Norwegian" msgstr "Норвешки" -#: ../gtk/propertybox.c:1077 +#: ../gtk/propertybox.c:1079 msgid "Hebrew" msgstr "" -#: ../gtk/propertybox.c:1078 +#: ../gtk/propertybox.c:1080 msgid "Serbian" msgstr "" -#: ../gtk/propertybox.c:1145 +#: ../gtk/propertybox.c:1147 msgid "" "You need to restart linphone for the new language selection to take effect." msgstr "" "Трба поново да покренете линфон да би нови изабрани језик ступио на снагу." -#: ../gtk/propertybox.c:1223 +#: ../gtk/propertybox.c:1225 msgid "None" msgstr "Ништа" -#: ../gtk/propertybox.c:1227 +#: ../gtk/propertybox.c:1229 msgid "SRTP" msgstr "СРТП" -#: ../gtk/propertybox.c:1233 +#: ../gtk/propertybox.c:1235 msgid "ZRTP" msgstr "ЗРТП" @@ -480,110 +480,114 @@ msgstr "" msgid "Enter your linphone.org username" msgstr "" -#: ../gtk/setupwizard.c:96 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 +#: ../gtk/setupwizard.c:102 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 msgid "Username:" msgstr "Корисничко име:" -#: ../gtk/setupwizard.c:98 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 +#: ../gtk/setupwizard.c:104 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 msgid "Password:" msgstr "Лозинка:" -#: ../gtk/setupwizard.c:118 +#: ../gtk/setupwizard.c:124 msgid "Enter your account informations" msgstr "" -#: ../gtk/setupwizard.c:125 +#: ../gtk/setupwizard.c:140 #, fuzzy msgid "Username*" msgstr "Корисничко име" -#: ../gtk/setupwizard.c:126 +#: ../gtk/setupwizard.c:141 #, fuzzy msgid "Password*" msgstr "Лозинка" -#: ../gtk/setupwizard.c:129 +#: ../gtk/setupwizard.c:144 msgid "Domain*" msgstr "" -#: ../gtk/setupwizard.c:130 +#: ../gtk/setupwizard.c:145 msgid "Proxy" msgstr "" -#: ../gtk/setupwizard.c:302 +#: ../gtk/setupwizard.c:317 msgid "(*) Required fields" msgstr "" -#: ../gtk/setupwizard.c:303 +#: ../gtk/setupwizard.c:318 #, fuzzy msgid "Username: (*)" msgstr "Корисничко име:" -#: ../gtk/setupwizard.c:305 +#: ../gtk/setupwizard.c:320 #, fuzzy msgid "Password: (*)" msgstr "Лозинка:" -#: ../gtk/setupwizard.c:307 +#: ../gtk/setupwizard.c:322 msgid "Email: (*)" msgstr "" -#: ../gtk/setupwizard.c:309 +#: ../gtk/setupwizard.c:324 msgid "Confirm your password: (*)" msgstr "" -#: ../gtk/setupwizard.c:373 +#: ../gtk/setupwizard.c:338 +msgid "Keep me informed with linphone updates" +msgstr "" + +#: ../gtk/setupwizard.c:394 msgid "" "Error, account not validated, username already used or server unreachable.\n" "Please go back and try again." msgstr "" -#: ../gtk/setupwizard.c:384 +#: ../gtk/setupwizard.c:405 msgid "Thank you. Your account is now configured and ready for use." msgstr "Хвала вам. Ваш налог је сада подешен и спреман за употребу." -#: ../gtk/setupwizard.c:392 +#: ../gtk/setupwizard.c:413 msgid "" "Please validate your account by clicking on the link we just sent you by " "email.\n" "Then come back here and press Next button." msgstr "" -#: ../gtk/setupwizard.c:564 +#: ../gtk/setupwizard.c:600 #, fuzzy msgid "SIP account configuration assistant" msgstr "Помоћник подешавања налога" -#: ../gtk/setupwizard.c:582 +#: ../gtk/setupwizard.c:618 msgid "Welcome to the account setup assistant" msgstr "Добродошли у помоћника подешавања налога" -#: ../gtk/setupwizard.c:587 +#: ../gtk/setupwizard.c:623 msgid "Account setup assistant" msgstr "Помоћник подешавања налога" -#: ../gtk/setupwizard.c:593 +#: ../gtk/setupwizard.c:629 #, fuzzy msgid "Configure your account (step 1/1)" msgstr "Подесите СИП налог" -#: ../gtk/setupwizard.c:598 +#: ../gtk/setupwizard.c:634 msgid "Enter your sip username (step 1/1)" msgstr "" -#: ../gtk/setupwizard.c:602 +#: ../gtk/setupwizard.c:638 msgid "Enter account information (step 1/2)" msgstr "" -#: ../gtk/setupwizard.c:611 +#: ../gtk/setupwizard.c:647 msgid "Validation (step 2/2)" msgstr "" -#: ../gtk/setupwizard.c:616 +#: ../gtk/setupwizard.c:652 msgid "Error" msgstr "" -#: ../gtk/setupwizard.c:620 ../gtk/audio_assistant.c:519 +#: ../gtk/setupwizard.c:656 ../gtk/audio_assistant.c:527 msgid "Terminating" msgstr "" @@ -655,131 +659,131 @@ msgstr "Позив није успео." msgid "Direct or through server" msgstr "" -#: ../gtk/incall_view.c:266 ../gtk/incall_view.c:276 +#: ../gtk/incall_view.c:267 ../gtk/incall_view.c:279 #, c-format msgid "" "download: %f\n" "upload: %f (kbit/s)" msgstr "" -#: ../gtk/incall_view.c:271 ../gtk/incall_view.c:272 +#: ../gtk/incall_view.c:272 ../gtk/incall_view.c:274 #, c-format -msgid "%ix%i" +msgid "%ix%i @ %f fps" msgstr "" -#: ../gtk/incall_view.c:301 +#: ../gtk/incall_view.c:304 #, fuzzy, c-format msgid "%.3f seconds" msgstr "%i секунда" -#: ../gtk/incall_view.c:399 ../gtk/main.ui.h:12 +#: ../gtk/incall_view.c:407 ../gtk/main.ui.h:12 msgid "Hang up" msgstr "" -#: ../gtk/incall_view.c:492 +#: ../gtk/incall_view.c:501 msgid "Calling..." msgstr "Позивам..." -#: ../gtk/incall_view.c:495 ../gtk/incall_view.c:698 +#: ../gtk/incall_view.c:504 ../gtk/incall_view.c:707 msgid "00::00::00" msgstr "00::00::00" -#: ../gtk/incall_view.c:506 +#: ../gtk/incall_view.c:515 msgid "Incoming call" msgstr "Долазни позив" -#: ../gtk/incall_view.c:543 +#: ../gtk/incall_view.c:552 msgid "good" msgstr "добро" -#: ../gtk/incall_view.c:545 +#: ../gtk/incall_view.c:554 msgid "average" msgstr "просечно" -#: ../gtk/incall_view.c:547 +#: ../gtk/incall_view.c:556 msgid "poor" msgstr "оскудно" -#: ../gtk/incall_view.c:549 +#: ../gtk/incall_view.c:558 msgid "very poor" msgstr "јадно" -#: ../gtk/incall_view.c:551 +#: ../gtk/incall_view.c:560 msgid "too bad" msgstr "много лоше" -#: ../gtk/incall_view.c:552 ../gtk/incall_view.c:568 +#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:577 msgid "unavailable" msgstr "недоступно" -#: ../gtk/incall_view.c:660 +#: ../gtk/incall_view.c:669 msgid "Secured by SRTP" msgstr "Осигурано СРТП-ом" -#: ../gtk/incall_view.c:666 +#: ../gtk/incall_view.c:675 #, c-format msgid "Secured by ZRTP - [auth token: %s]" msgstr "Осигурано ЗРТП-ом [потврђивање идентитета: %s]" -#: ../gtk/incall_view.c:672 +#: ../gtk/incall_view.c:681 msgid "Set unverified" msgstr "Непроверено подешавање" -#: ../gtk/incall_view.c:672 ../gtk/main.ui.h:4 +#: ../gtk/incall_view.c:681 ../gtk/main.ui.h:4 msgid "Set verified" msgstr "Проверено подешавање" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In conference" msgstr "На конференцији" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In call" msgstr "У позиву" -#: ../gtk/incall_view.c:729 +#: ../gtk/incall_view.c:738 msgid "Paused call" msgstr "Заустављен позив" -#: ../gtk/incall_view.c:742 +#: ../gtk/incall_view.c:751 #, c-format msgid "%02i::%02i::%02i" msgstr "%02i::%02i::%02i" -#: ../gtk/incall_view.c:760 +#: ../gtk/incall_view.c:772 msgid "Call ended." msgstr "Позив је завршен." -#: ../gtk/incall_view.c:791 +#: ../gtk/incall_view.c:803 msgid "Transfer in progress" msgstr "" -#: ../gtk/incall_view.c:794 +#: ../gtk/incall_view.c:806 #, fuzzy msgid "Transfer done." msgstr "Пребаци" -#: ../gtk/incall_view.c:797 +#: ../gtk/incall_view.c:809 #, fuzzy msgid "Transfer failed." msgstr "Пребаци" -#: ../gtk/incall_view.c:841 +#: ../gtk/incall_view.c:853 msgid "Resume" msgstr "Настави" -#: ../gtk/incall_view.c:848 ../gtk/main.ui.h:9 +#: ../gtk/incall_view.c:860 ../gtk/main.ui.h:9 msgid "Pause" msgstr "Застани" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, c-format msgid "" "Recording into\n" "%s %s" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, fuzzy msgid "(Paused)" msgstr "Застани" @@ -815,7 +819,7 @@ msgstr "" msgid "Too loud" msgstr "" -#: ../gtk/audio_assistant.c:316 +#: ../gtk/audio_assistant.c:318 #, fuzzy msgid "" "Welcome !\n" @@ -824,59 +828,59 @@ msgstr "" "Добродошли !\n" "Овај помоћник ће вам помоћи да користите СИП налог за ваше позиве." -#: ../gtk/audio_assistant.c:326 +#: ../gtk/audio_assistant.c:328 #, fuzzy msgid "Capture device" msgstr "Уређај за снимање:" -#: ../gtk/audio_assistant.c:327 +#: ../gtk/audio_assistant.c:329 msgid "Recorded volume" msgstr "" -#: ../gtk/audio_assistant.c:331 +#: ../gtk/audio_assistant.c:333 msgid "No voice" msgstr "" -#: ../gtk/audio_assistant.c:367 +#: ../gtk/audio_assistant.c:369 #, fuzzy msgid "Playback device" msgstr "Уређај за пуштање:" -#: ../gtk/audio_assistant.c:368 +#: ../gtk/audio_assistant.c:370 msgid "Play three beeps" msgstr "" -#: ../gtk/audio_assistant.c:400 +#: ../gtk/audio_assistant.c:403 msgid "Press the record button and say some words" msgstr "" -#: ../gtk/audio_assistant.c:401 +#: ../gtk/audio_assistant.c:404 msgid "Listen to your record voice" msgstr "" -#: ../gtk/audio_assistant.c:430 +#: ../gtk/audio_assistant.c:433 msgid "Let's start Linphone now" msgstr "" -#: ../gtk/audio_assistant.c:488 +#: ../gtk/audio_assistant.c:496 #, fuzzy msgid "Audio Assistant" msgstr "Помоћник подешавања налога" -#: ../gtk/audio_assistant.c:498 ../gtk/main.ui.h:31 +#: ../gtk/audio_assistant.c:506 ../gtk/main.ui.h:31 #, fuzzy msgid "Audio assistant" msgstr "Помоћник подешавања налога" -#: ../gtk/audio_assistant.c:503 +#: ../gtk/audio_assistant.c:511 msgid "Mic Gain calibration" msgstr "" -#: ../gtk/audio_assistant.c:509 +#: ../gtk/audio_assistant.c:517 msgid "Speaker volume calibration" msgstr "" -#: ../gtk/audio_assistant.c:514 +#: ../gtk/audio_assistant.c:522 msgid "Record and Play" msgstr "" @@ -1829,96 +1833,65 @@ msgstr "Повезујем се..." msgid "Please wait while fetching configuration from server..." msgstr "" -#: ../coreapi/linphonecore.c:242 -msgid "aborted" -msgstr "прекинути" - -#: ../coreapi/linphonecore.c:245 -msgid "completed" -msgstr "завршени" - -#: ../coreapi/linphonecore.c:248 -msgid "missed" -msgstr "пропуштени" - -#: ../coreapi/linphonecore.c:253 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" -"%s у %s\n" -"Позива: %s\n" -"Прима: %s\n" -"Стање: %s\n" -"Трајање: %i мин %i сек\n" - -#: ../coreapi/linphonecore.c:254 -msgid "Outgoing call" -msgstr "Одлазни позив" - -#: ../coreapi/linphonecore.c:1287 +#: ../coreapi/linphonecore.c:1034 msgid "Ready" msgstr "Спреман" -#: ../coreapi/linphonecore.c:2248 +#: ../coreapi/linphonecore.c:1967 #, fuzzy msgid "Configuring" msgstr "Потврђујем" -#: ../coreapi/linphonecore.c:2410 +#: ../coreapi/linphonecore.c:2133 msgid "Looking for telephone number destination..." msgstr "Тражим одредиште телефонског броја..." -#: ../coreapi/linphonecore.c:2413 +#: ../coreapi/linphonecore.c:2136 msgid "Could not resolve this number." msgstr "Не могу да решим овај број." #. must be known at that time -#: ../coreapi/linphonecore.c:2695 +#: ../coreapi/linphonecore.c:2418 msgid "Contacting" msgstr "Ступам у везу" -#: ../coreapi/linphonecore.c:2702 +#: ../coreapi/linphonecore.c:2425 msgid "Could not call" msgstr "Не могу да позовем" -#: ../coreapi/linphonecore.c:2852 +#: ../coreapi/linphonecore.c:2576 msgid "Sorry, we have reached the maximum number of simultaneous calls" msgstr "Извините, достигли смо највећи број истовремених позива" -#: ../coreapi/linphonecore.c:3022 +#: ../coreapi/linphonecore.c:2745 msgid "is contacting you" msgstr "вам се обраћа" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid " and asked autoanswer." msgstr " и затражени само-одговор." -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid "." msgstr "." -#: ../coreapi/linphonecore.c:3139 +#: ../coreapi/linphonecore.c:2865 msgid "Modifying call parameters..." msgstr "Мењам параметре позива..." -#: ../coreapi/linphonecore.c:3469 +#: ../coreapi/linphonecore.c:3194 msgid "Connected." msgstr "Повезан сам." -#: ../coreapi/linphonecore.c:3495 +#: ../coreapi/linphonecore.c:3220 msgid "Call aborted" msgstr "Позив је прекинут" -#: ../coreapi/linphonecore.c:3685 +#: ../coreapi/linphonecore.c:3412 msgid "Could not pause the call" msgstr "Не могу да зауставим позив" -#: ../coreapi/linphonecore.c:3690 +#: ../coreapi/linphonecore.c:3417 msgid "Pausing the current call..." msgstr "Заустављам тренутни позив..." @@ -1983,7 +1956,7 @@ msgstr "Трајање" msgid "Unknown-bug" msgstr "Непозната грешка" -#: ../coreapi/proxy.c:279 +#: ../coreapi/proxy.c:314 msgid "" "The sip proxy address you entered is invalid, it must start with \"sip:\" " "followed by a hostname." @@ -1991,7 +1964,7 @@ msgstr "" "Адреса сип посредника коју сте унели је неисправна, мора почети на „sip:“ за " "којим следи назив домаћина." -#: ../coreapi/proxy.c:285 +#: ../coreapi/proxy.c:320 msgid "" "The sip identity you entered is invalid.\n" "It should look like sip:username@proxydomain, such as sip:alice@example.net" @@ -2000,126 +1973,126 @@ msgstr "" "Треба да изгледа као „sip:корисник@домен-посредника, као што је „sip:" "alice@example.net“" -#: ../coreapi/proxy.c:1299 +#: ../coreapi/proxy.c:1369 #, c-format msgid "Could not login as %s" msgstr "Не могу да се пријавим као %s" -#: ../coreapi/callbacks.c:354 +#: ../coreapi/callbacks.c:355 msgid "Remote ringing." msgstr "Удаљено звоњење." -#: ../coreapi/callbacks.c:370 +#: ../coreapi/callbacks.c:373 msgid "Remote ringing..." msgstr "Удаљено звоњење..." -#: ../coreapi/callbacks.c:381 +#: ../coreapi/callbacks.c:384 msgid "Early media." msgstr "Ранији медиј." -#: ../coreapi/callbacks.c:432 +#: ../coreapi/callbacks.c:435 #, c-format msgid "Call with %s is paused." msgstr "Позив са „%s“ је заустављен." -#: ../coreapi/callbacks.c:445 +#: ../coreapi/callbacks.c:448 #, c-format msgid "Call answered by %s - on hold." msgstr "Позив на који је одговорио „%s“ — на чекању." -#: ../coreapi/callbacks.c:456 +#: ../coreapi/callbacks.c:459 msgid "Call resumed." msgstr "Позив је настављен." -#: ../coreapi/callbacks.c:461 +#: ../coreapi/callbacks.c:464 #, c-format msgid "Call answered by %s." msgstr "На позив је одговорио „%s“." -#: ../coreapi/callbacks.c:480 +#: ../coreapi/callbacks.c:483 msgid "Incompatible, check codecs or security settings..." msgstr "" -#: ../coreapi/callbacks.c:531 +#: ../coreapi/callbacks.c:512 #, fuzzy msgid "We have been resumed." msgstr "Позив нам је настављен..." -#: ../coreapi/callbacks.c:541 +#: ../coreapi/callbacks.c:521 msgid "We are paused by other party." msgstr "" -#: ../coreapi/callbacks.c:558 +#: ../coreapi/callbacks.c:556 #, fuzzy msgid "Call is updated by remote." msgstr "Позив је ажуриран удаљеним..." -#: ../coreapi/callbacks.c:637 +#: ../coreapi/callbacks.c:658 msgid "Call terminated." msgstr "Позив је завршен." -#: ../coreapi/callbacks.c:666 +#: ../coreapi/callbacks.c:687 msgid "User is busy." msgstr "Корисник је заузет." -#: ../coreapi/callbacks.c:667 +#: ../coreapi/callbacks.c:688 msgid "User is temporarily unavailable." msgstr "Корисник је привремено недоступан." #. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:669 +#: ../coreapi/callbacks.c:690 msgid "User does not want to be disturbed." msgstr "Корисник не жели да буде узнемираван." -#: ../coreapi/callbacks.c:670 +#: ../coreapi/callbacks.c:691 msgid "Call declined." msgstr "Позив је одбијен." -#: ../coreapi/callbacks.c:685 +#: ../coreapi/callbacks.c:706 msgid "Request timeout." msgstr "" -#: ../coreapi/callbacks.c:716 +#: ../coreapi/callbacks.c:737 msgid "Redirected" msgstr "Преусмерен" -#: ../coreapi/callbacks.c:766 +#: ../coreapi/callbacks.c:787 msgid "Incompatible media parameters." msgstr "" -#: ../coreapi/callbacks.c:777 +#: ../coreapi/callbacks.c:798 msgid "Call failed." msgstr "Позив није успео." -#: ../coreapi/callbacks.c:852 +#: ../coreapi/callbacks.c:878 #, c-format msgid "Registration on %s successful." msgstr "Уписивање на „%s“ је успело." -#: ../coreapi/callbacks.c:853 +#: ../coreapi/callbacks.c:879 #, c-format msgid "Unregistration on %s done." msgstr "Исписивање са „%s“ је обављено." -#: ../coreapi/callbacks.c:875 +#: ../coreapi/callbacks.c:897 msgid "no response timeout" msgstr "нема ограничења одговора" -#: ../coreapi/callbacks.c:878 +#: ../coreapi/callbacks.c:900 #, c-format msgid "Registration on %s failed: %s" msgstr "Уписивање на „%s“ није успело: %s" -#: ../coreapi/callbacks.c:885 +#: ../coreapi/callbacks.c:907 msgid "Service unavailable, retrying" msgstr "" -#: ../coreapi/linphonecall.c:175 +#: ../coreapi/linphonecall.c:177 #, c-format msgid "Authentication token is %s" msgstr "Симбол потврђивања идентитета је „%s“" -#: ../coreapi/linphonecall.c:2994 +#: ../coreapi/linphonecall.c:2932 #, c-format msgid "You have missed %i call." msgid_plural "You have missed %i calls." @@ -2128,6 +2101,31 @@ msgstr[1] "Пропустили сте %i позива." msgstr[2] "Пропустили сте %i позива." msgstr[3] "Пропустили сте један позив." +#~ msgid "aborted" +#~ msgstr "прекинути" + +#~ msgid "completed" +#~ msgstr "завршени" + +#~ msgid "missed" +#~ msgstr "пропуштени" + +#~ msgid "" +#~ "%s at %s\n" +#~ "From: %s\n" +#~ "To: %s\n" +#~ "Status: %s\n" +#~ "Duration: %i mn %i sec\n" +#~ msgstr "" +#~ "%s у %s\n" +#~ "Позива: %s\n" +#~ "Прима: %s\n" +#~ "Стање: %s\n" +#~ "Трајање: %i мин %i сек\n" + +#~ msgid "Outgoing call" +#~ msgstr "Одлазни позив" + #~ msgid "No response." #~ msgstr "Нема одговора." diff --git a/po/sv.po b/po/sv.po index 67e07eab8..59b307d05 100644 --- a/po/sv.po +++ b/po/sv.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-01 21:24+0200\n" +"POT-Creation-Date: 2014-09-15 09:24+0200\n" "PO-Revision-Date: 2009-02-17 15:22+0100\n" "Last-Translator: Emmanuel Frécon \n" "Language-Team: SWEDISH \n" @@ -16,12 +16,12 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:973 +#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:974 #, c-format msgid "Call %s" msgstr "Ringer %s" -#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:974 +#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:975 #, c-format msgid "Send text to %s" msgstr "Skicka text till %s" @@ -31,52 +31,52 @@ msgstr "Skicka text till %s" msgid "Recent calls (%i)" msgstr "I samtal med" -#: ../gtk/calllogs.c:312 +#: ../gtk/calllogs.c:314 msgid "n/a" msgstr "" -#: ../gtk/calllogs.c:315 +#: ../gtk/calllogs.c:317 #, fuzzy msgid "Aborted" msgstr "avbrytade" -#: ../gtk/calllogs.c:318 +#: ../gtk/calllogs.c:320 #, fuzzy msgid "Missed" msgstr "missade" -#: ../gtk/calllogs.c:321 +#: ../gtk/calllogs.c:323 #, fuzzy msgid "Declined" msgstr "Avböj" -#: ../gtk/calllogs.c:327 +#: ../gtk/calllogs.c:329 #, c-format msgid "%i minute" msgid_plural "%i minutes" msgstr[0] "" msgstr[1] "" -#: ../gtk/calllogs.c:330 +#: ../gtk/calllogs.c:332 #, c-format msgid "%i second" msgid_plural "%i seconds" msgstr[0] "" msgstr[1] "" -#: ../gtk/calllogs.c:333 ../gtk/calllogs.c:339 +#: ../gtk/calllogs.c:335 ../gtk/calllogs.c:341 #, c-format msgid "%s\t%s" msgstr "" -#: ../gtk/calllogs.c:335 +#: ../gtk/calllogs.c:337 #, c-format msgid "" "%s\tQuality: %s\n" "%s\t%s\t" msgstr "" -#: ../gtk/calllogs.c:341 +#: ../gtk/calllogs.c:343 #, c-format msgid "" "%s\t\n" @@ -97,7 +97,7 @@ msgstr "Mikrofon av" msgid "Couldn't find pixmap file: %s" msgstr "Kunde inte hitta pixmap filen: %s" -#: ../gtk/chat.c:363 ../gtk/friendlist.c:923 +#: ../gtk/chat.c:364 ../gtk/friendlist.c:924 msgid "Invalid sip contact !" msgstr "ogiltig SIP kontakt!" @@ -148,7 +148,7 @@ msgstr "Kontoinstallationsassistenten" msgid "Call with %s" msgstr "Samtal med %s" -#: ../gtk/main.c:1171 +#: ../gtk/main.c:1183 #, c-format msgid "" "%s would like to add you to his contact list.\n" @@ -161,7 +161,7 @@ msgstr "" "henne till din kontaktlista?\n" "Om du svarar nej, personen kommer att vara bannlyst." -#: ../gtk/main.c:1248 +#: ../gtk/main.c:1260 #, fuzzy, c-format msgid "" "Please enter your password for username %s\n" @@ -170,67 +170,67 @@ msgstr "" "Mata in ditt lösenord för användaren %s\n" "vid domänen %s:" -#: ../gtk/main.c:1364 +#: ../gtk/main.c:1376 #, fuzzy msgid "Call error" msgstr "Samtalshistorik" -#: ../gtk/main.c:1367 ../coreapi/linphonecore.c:3515 +#: ../gtk/main.c:1379 ../coreapi/linphonecore.c:3240 msgid "Call ended" msgstr "Samtalet slut" -#: ../gtk/main.c:1370 ../coreapi/linphonecore.c:254 +#: ../gtk/main.c:1382 msgid "Incoming call" msgstr "Inkommande samtal" -#: ../gtk/main.c:1372 ../gtk/incall_view.c:513 ../gtk/main.ui.h:5 +#: ../gtk/main.c:1384 ../gtk/incall_view.c:522 ../gtk/main.ui.h:5 msgid "Answer" msgstr "" -#: ../gtk/main.c:1374 ../gtk/main.ui.h:6 +#: ../gtk/main.c:1386 ../gtk/main.ui.h:6 msgid "Decline" msgstr "Avböj" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy msgid "Call paused" msgstr "avbrytade" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy, c-format msgid "by %s" msgstr "Portar" -#: ../gtk/main.c:1447 +#: ../gtk/main.c:1459 #, c-format msgid "%s proposed to start video. Do you accept ?" msgstr "" -#: ../gtk/main.c:1609 +#: ../gtk/main.c:1621 msgid "Website link" msgstr "Webbsajt" -#: ../gtk/main.c:1658 +#: ../gtk/main.c:1670 msgid "Linphone - a video internet phone" msgstr "Linphone - en video Internet telefon" -#: ../gtk/main.c:1750 +#: ../gtk/main.c:1762 #, c-format msgid "%s (Default)" msgstr "%s (Default)" -#: ../gtk/main.c:2086 ../coreapi/callbacks.c:927 +#: ../gtk/main.c:2099 ../coreapi/callbacks.c:949 #, c-format msgid "We are transferred to %s" msgstr "" -#: ../gtk/main.c:2096 +#: ../gtk/main.c:2109 msgid "" "No sound cards have been detected on this computer.\n" "You won't be able to send or receive audio calls." msgstr "" -#: ../gtk/main.c:2237 +#: ../gtk/main.c:2250 msgid "A free SIP video-phone" msgstr "En gratis SIP video-telefon" @@ -242,7 +242,7 @@ msgstr "" msgid "Presence status" msgstr "Närvarostatus" -#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:550 ../gtk/contact.ui.h:1 +#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:552 ../gtk/contact.ui.h:1 msgid "Name" msgstr "Namn" @@ -260,141 +260,141 @@ msgstr "" msgid "Search in %s directory" msgstr "Sök i %s katalogen" -#: ../gtk/friendlist.c:975 +#: ../gtk/friendlist.c:976 #, c-format msgid "Edit contact '%s'" msgstr "Ändra kontakt '%s'" -#: ../gtk/friendlist.c:976 +#: ../gtk/friendlist.c:977 #, c-format msgid "Delete contact '%s'" msgstr "Ta bort kontakt '%s'" -#: ../gtk/friendlist.c:977 +#: ../gtk/friendlist.c:978 #, fuzzy, c-format msgid "Delete chat history of '%s'" msgstr "Ta bort kontakt '%s'" -#: ../gtk/friendlist.c:1028 +#: ../gtk/friendlist.c:1029 #, c-format msgid "Add new contact from %s directory" msgstr "Lägg till kontakt ifrån %s katalogen" -#: ../gtk/propertybox.c:556 +#: ../gtk/propertybox.c:558 msgid "Rate (Hz)" msgstr "Frekvens (Hz)" -#: ../gtk/propertybox.c:562 +#: ../gtk/propertybox.c:564 msgid "Status" msgstr "Status" -#: ../gtk/propertybox.c:568 +#: ../gtk/propertybox.c:570 #, fuzzy msgid "IP Bitrate (kbit/s)" msgstr "Min. datahastighet (kbit/s)" -#: ../gtk/propertybox.c:575 +#: ../gtk/propertybox.c:577 msgid "Parameters" msgstr "Parametrar" -#: ../gtk/propertybox.c:618 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:763 msgid "Enabled" msgstr "På" -#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:622 ../gtk/propertybox.c:763 msgid "Disabled" msgstr "Av" -#: ../gtk/propertybox.c:807 +#: ../gtk/propertybox.c:809 msgid "Account" msgstr "Konto" -#: ../gtk/propertybox.c:1061 +#: ../gtk/propertybox.c:1063 msgid "English" msgstr "Engelska" -#: ../gtk/propertybox.c:1062 +#: ../gtk/propertybox.c:1064 msgid "French" msgstr "Fransk" -#: ../gtk/propertybox.c:1063 +#: ../gtk/propertybox.c:1065 msgid "Swedish" msgstr "Svenska" -#: ../gtk/propertybox.c:1064 +#: ../gtk/propertybox.c:1066 msgid "Italian" msgstr "Italiensk" -#: ../gtk/propertybox.c:1065 +#: ../gtk/propertybox.c:1067 msgid "Spanish" msgstr "Spanska" -#: ../gtk/propertybox.c:1066 +#: ../gtk/propertybox.c:1068 msgid "Brazilian Portugese" msgstr "Portugisiska" -#: ../gtk/propertybox.c:1067 +#: ../gtk/propertybox.c:1069 msgid "Polish" msgstr "Polska" -#: ../gtk/propertybox.c:1068 +#: ../gtk/propertybox.c:1070 msgid "German" msgstr "Tyska" -#: ../gtk/propertybox.c:1069 +#: ../gtk/propertybox.c:1071 msgid "Russian" msgstr "Ryska" -#: ../gtk/propertybox.c:1070 +#: ../gtk/propertybox.c:1072 msgid "Japanese" msgstr "Japanska" -#: ../gtk/propertybox.c:1071 +#: ../gtk/propertybox.c:1073 msgid "Dutch" msgstr "Nederländksa" -#: ../gtk/propertybox.c:1072 +#: ../gtk/propertybox.c:1074 msgid "Hungarian" msgstr "Hungerska" -#: ../gtk/propertybox.c:1073 +#: ../gtk/propertybox.c:1075 msgid "Czech" msgstr "Tjekiska" -#: ../gtk/propertybox.c:1074 +#: ../gtk/propertybox.c:1076 msgid "Chinese" msgstr "Kinesiska" -#: ../gtk/propertybox.c:1075 +#: ../gtk/propertybox.c:1077 msgid "Traditional Chinese" msgstr "" -#: ../gtk/propertybox.c:1076 +#: ../gtk/propertybox.c:1078 msgid "Norwegian" msgstr "" -#: ../gtk/propertybox.c:1077 +#: ../gtk/propertybox.c:1079 msgid "Hebrew" msgstr "" -#: ../gtk/propertybox.c:1078 +#: ../gtk/propertybox.c:1080 msgid "Serbian" msgstr "" -#: ../gtk/propertybox.c:1145 +#: ../gtk/propertybox.c:1147 msgid "" "You need to restart linphone for the new language selection to take effect." msgstr "Du behöver starta om programmet för att det nya språket ska synas." -#: ../gtk/propertybox.c:1223 +#: ../gtk/propertybox.c:1225 msgid "None" msgstr "" -#: ../gtk/propertybox.c:1227 +#: ../gtk/propertybox.c:1229 msgid "SRTP" msgstr "" -#: ../gtk/propertybox.c:1233 +#: ../gtk/propertybox.c:1235 msgid "ZRTP" msgstr "" @@ -469,110 +469,114 @@ msgstr "" msgid "Enter your linphone.org username" msgstr "" -#: ../gtk/setupwizard.c:96 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 +#: ../gtk/setupwizard.c:102 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 msgid "Username:" msgstr "Användarnamn:" -#: ../gtk/setupwizard.c:98 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 +#: ../gtk/setupwizard.c:104 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 msgid "Password:" msgstr "Lösenord:" -#: ../gtk/setupwizard.c:118 +#: ../gtk/setupwizard.c:124 msgid "Enter your account informations" msgstr "" -#: ../gtk/setupwizard.c:125 +#: ../gtk/setupwizard.c:140 #, fuzzy msgid "Username*" msgstr "Användarnamn" -#: ../gtk/setupwizard.c:126 +#: ../gtk/setupwizard.c:141 #, fuzzy msgid "Password*" msgstr "Lösenord" -#: ../gtk/setupwizard.c:129 +#: ../gtk/setupwizard.c:144 msgid "Domain*" msgstr "" -#: ../gtk/setupwizard.c:130 +#: ../gtk/setupwizard.c:145 msgid "Proxy" msgstr "" -#: ../gtk/setupwizard.c:302 +#: ../gtk/setupwizard.c:317 msgid "(*) Required fields" msgstr "" -#: ../gtk/setupwizard.c:303 +#: ../gtk/setupwizard.c:318 #, fuzzy msgid "Username: (*)" msgstr "Användarnamn:" -#: ../gtk/setupwizard.c:305 +#: ../gtk/setupwizard.c:320 #, fuzzy msgid "Password: (*)" msgstr "Lösenord:" -#: ../gtk/setupwizard.c:307 +#: ../gtk/setupwizard.c:322 msgid "Email: (*)" msgstr "" -#: ../gtk/setupwizard.c:309 +#: ../gtk/setupwizard.c:324 msgid "Confirm your password: (*)" msgstr "" -#: ../gtk/setupwizard.c:373 +#: ../gtk/setupwizard.c:338 +msgid "Keep me informed with linphone updates" +msgstr "" + +#: ../gtk/setupwizard.c:394 msgid "" "Error, account not validated, username already used or server unreachable.\n" "Please go back and try again." msgstr "" -#: ../gtk/setupwizard.c:384 +#: ../gtk/setupwizard.c:405 msgid "Thank you. Your account is now configured and ready for use." msgstr "Tack. Ditt konto är nu konfigurerad och färdig att användas." -#: ../gtk/setupwizard.c:392 +#: ../gtk/setupwizard.c:413 msgid "" "Please validate your account by clicking on the link we just sent you by " "email.\n" "Then come back here and press Next button." msgstr "" -#: ../gtk/setupwizard.c:564 +#: ../gtk/setupwizard.c:600 #, fuzzy msgid "SIP account configuration assistant" msgstr "Kontoinstallationsassistenten" -#: ../gtk/setupwizard.c:582 +#: ../gtk/setupwizard.c:618 msgid "Welcome to the account setup assistant" msgstr "Välkommen till kontoinstallationsassistenten" -#: ../gtk/setupwizard.c:587 +#: ../gtk/setupwizard.c:623 msgid "Account setup assistant" msgstr "Kontoinstallationsassistenten" -#: ../gtk/setupwizard.c:593 +#: ../gtk/setupwizard.c:629 #, fuzzy msgid "Configure your account (step 1/1)" msgstr "Konfigurera ett SIP konto" -#: ../gtk/setupwizard.c:598 +#: ../gtk/setupwizard.c:634 msgid "Enter your sip username (step 1/1)" msgstr "" -#: ../gtk/setupwizard.c:602 +#: ../gtk/setupwizard.c:638 msgid "Enter account information (step 1/2)" msgstr "" -#: ../gtk/setupwizard.c:611 +#: ../gtk/setupwizard.c:647 msgid "Validation (step 2/2)" msgstr "" -#: ../gtk/setupwizard.c:616 +#: ../gtk/setupwizard.c:652 msgid "Error" msgstr "" -#: ../gtk/setupwizard.c:620 ../gtk/audio_assistant.c:519 +#: ../gtk/setupwizard.c:656 ../gtk/audio_assistant.c:527 #, fuzzy msgid "Terminating" msgstr "Lägg på" @@ -643,133 +647,133 @@ msgstr "Samtalet avböjdes." msgid "Direct or through server" msgstr "" -#: ../gtk/incall_view.c:266 ../gtk/incall_view.c:276 +#: ../gtk/incall_view.c:267 ../gtk/incall_view.c:279 #, c-format msgid "" "download: %f\n" "upload: %f (kbit/s)" msgstr "" -#: ../gtk/incall_view.c:271 ../gtk/incall_view.c:272 +#: ../gtk/incall_view.c:272 ../gtk/incall_view.c:274 #, c-format -msgid "%ix%i" +msgid "%ix%i @ %f fps" msgstr "" -#: ../gtk/incall_view.c:301 +#: ../gtk/incall_view.c:304 #, c-format msgid "%.3f seconds" msgstr "" -#: ../gtk/incall_view.c:399 ../gtk/main.ui.h:12 +#: ../gtk/incall_view.c:407 ../gtk/main.ui.h:12 msgid "Hang up" msgstr "" -#: ../gtk/incall_view.c:492 +#: ../gtk/incall_view.c:501 msgid "Calling..." msgstr "Ringer..." -#: ../gtk/incall_view.c:495 ../gtk/incall_view.c:698 +#: ../gtk/incall_view.c:504 ../gtk/incall_view.c:707 msgid "00::00::00" msgstr "00:00:00" -#: ../gtk/incall_view.c:506 +#: ../gtk/incall_view.c:515 #, fuzzy msgid "Incoming call" msgstr "Inkommande samtal" -#: ../gtk/incall_view.c:543 +#: ../gtk/incall_view.c:552 msgid "good" msgstr "" -#: ../gtk/incall_view.c:545 +#: ../gtk/incall_view.c:554 msgid "average" msgstr "" -#: ../gtk/incall_view.c:547 +#: ../gtk/incall_view.c:556 msgid "poor" msgstr "" -#: ../gtk/incall_view.c:549 +#: ../gtk/incall_view.c:558 msgid "very poor" msgstr "" -#: ../gtk/incall_view.c:551 +#: ../gtk/incall_view.c:560 msgid "too bad" msgstr "" -#: ../gtk/incall_view.c:552 ../gtk/incall_view.c:568 +#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:577 msgid "unavailable" msgstr "" -#: ../gtk/incall_view.c:660 +#: ../gtk/incall_view.c:669 msgid "Secured by SRTP" msgstr "" -#: ../gtk/incall_view.c:666 +#: ../gtk/incall_view.c:675 #, c-format msgid "Secured by ZRTP - [auth token: %s]" msgstr "" -#: ../gtk/incall_view.c:672 +#: ../gtk/incall_view.c:681 msgid "Set unverified" msgstr "" -#: ../gtk/incall_view.c:672 ../gtk/main.ui.h:4 +#: ../gtk/incall_view.c:681 ../gtk/main.ui.h:4 msgid "Set verified" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In conference" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 #, fuzzy msgid "In call" msgstr "I samtal med" -#: ../gtk/incall_view.c:729 +#: ../gtk/incall_view.c:738 #, fuzzy msgid "Paused call" msgstr "Lägg på" -#: ../gtk/incall_view.c:742 +#: ../gtk/incall_view.c:751 #, c-format msgid "%02i::%02i::%02i" msgstr "%02i:%02i:%02i" -#: ../gtk/incall_view.c:760 +#: ../gtk/incall_view.c:772 msgid "Call ended." msgstr "Samtalet slut." -#: ../gtk/incall_view.c:791 +#: ../gtk/incall_view.c:803 msgid "Transfer in progress" msgstr "" -#: ../gtk/incall_view.c:794 +#: ../gtk/incall_view.c:806 msgid "Transfer done." msgstr "" -#: ../gtk/incall_view.c:797 +#: ../gtk/incall_view.c:809 #, fuzzy msgid "Transfer failed." msgstr "Samtalet avböjdes." -#: ../gtk/incall_view.c:841 +#: ../gtk/incall_view.c:853 msgid "Resume" msgstr "" -#: ../gtk/incall_view.c:848 ../gtk/main.ui.h:9 +#: ../gtk/incall_view.c:860 ../gtk/main.ui.h:9 msgid "Pause" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, c-format msgid "" "Recording into\n" "%s %s" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 msgid "(Paused)" msgstr "" @@ -804,7 +808,7 @@ msgstr "" msgid "Too loud" msgstr "" -#: ../gtk/audio_assistant.c:316 +#: ../gtk/audio_assistant.c:318 #, fuzzy msgid "" "Welcome !\n" @@ -813,59 +817,59 @@ msgstr "" "Välkommen!\n" "Assistenten kommer att hjälpa dig använda ett SIP konto för dina samtal:" -#: ../gtk/audio_assistant.c:326 +#: ../gtk/audio_assistant.c:328 #, fuzzy msgid "Capture device" msgstr "Mikrofon enhet:" -#: ../gtk/audio_assistant.c:327 +#: ../gtk/audio_assistant.c:329 msgid "Recorded volume" msgstr "" -#: ../gtk/audio_assistant.c:331 +#: ../gtk/audio_assistant.c:333 msgid "No voice" msgstr "" -#: ../gtk/audio_assistant.c:367 +#: ../gtk/audio_assistant.c:369 #, fuzzy msgid "Playback device" msgstr "Uppspelningsenhet:" -#: ../gtk/audio_assistant.c:368 +#: ../gtk/audio_assistant.c:370 msgid "Play three beeps" msgstr "" -#: ../gtk/audio_assistant.c:400 +#: ../gtk/audio_assistant.c:403 msgid "Press the record button and say some words" msgstr "" -#: ../gtk/audio_assistant.c:401 +#: ../gtk/audio_assistant.c:404 msgid "Listen to your record voice" msgstr "" -#: ../gtk/audio_assistant.c:430 +#: ../gtk/audio_assistant.c:433 msgid "Let's start Linphone now" msgstr "" -#: ../gtk/audio_assistant.c:488 +#: ../gtk/audio_assistant.c:496 #, fuzzy msgid "Audio Assistant" msgstr "Assistent" -#: ../gtk/audio_assistant.c:498 ../gtk/main.ui.h:31 +#: ../gtk/audio_assistant.c:506 ../gtk/main.ui.h:31 #, fuzzy msgid "Audio assistant" msgstr "Kontoinstallationsassistenten" -#: ../gtk/audio_assistant.c:503 +#: ../gtk/audio_assistant.c:511 msgid "Mic Gain calibration" msgstr "" -#: ../gtk/audio_assistant.c:509 +#: ../gtk/audio_assistant.c:517 msgid "Speaker volume calibration" msgstr "" -#: ../gtk/audio_assistant.c:514 +#: ../gtk/audio_assistant.c:522 msgid "Record and Play" msgstr "" @@ -1827,100 +1831,69 @@ msgstr "Kontaktar" msgid "Please wait while fetching configuration from server..." msgstr "" -#: ../coreapi/linphonecore.c:242 -msgid "aborted" -msgstr "avbrytade" - -#: ../coreapi/linphonecore.c:245 -msgid "completed" -msgstr "avslutade" - -#: ../coreapi/linphonecore.c:248 -msgid "missed" -msgstr "missade" - -#: ../coreapi/linphonecore.c:253 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" -"%s på %s\n" -"Från: %s\n" -"Till: %s\n" -"Status: %s\n" -"Längd: %i min %i sek\n" - -#: ../coreapi/linphonecore.c:254 -msgid "Outgoing call" -msgstr "Utgående samtal" - -#: ../coreapi/linphonecore.c:1287 +#: ../coreapi/linphonecore.c:1034 msgid "Ready" msgstr "Redo" -#: ../coreapi/linphonecore.c:2248 +#: ../coreapi/linphonecore.c:1967 #, fuzzy msgid "Configuring" msgstr "Bekräftelse" -#: ../coreapi/linphonecore.c:2410 +#: ../coreapi/linphonecore.c:2133 msgid "Looking for telephone number destination..." msgstr "Leta efter telefonnummer för destinationen..." -#: ../coreapi/linphonecore.c:2413 +#: ../coreapi/linphonecore.c:2136 msgid "Could not resolve this number." msgstr "Kan inte nå dett nummer." #. must be known at that time -#: ../coreapi/linphonecore.c:2695 +#: ../coreapi/linphonecore.c:2418 msgid "Contacting" msgstr "Kontaktar" -#: ../coreapi/linphonecore.c:2702 +#: ../coreapi/linphonecore.c:2425 #, fuzzy msgid "Could not call" msgstr "Kunde inte ringa" -#: ../coreapi/linphonecore.c:2852 +#: ../coreapi/linphonecore.c:2576 msgid "Sorry, we have reached the maximum number of simultaneous calls" msgstr "" -#: ../coreapi/linphonecore.c:3022 +#: ../coreapi/linphonecore.c:2745 #, fuzzy msgid "is contacting you" msgstr "kontaktar dig." -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid " and asked autoanswer." msgstr "" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid "." msgstr "" -#: ../coreapi/linphonecore.c:3139 +#: ../coreapi/linphonecore.c:2865 msgid "Modifying call parameters..." msgstr "" -#: ../coreapi/linphonecore.c:3469 +#: ../coreapi/linphonecore.c:3194 msgid "Connected." msgstr "Kopplad" -#: ../coreapi/linphonecore.c:3495 +#: ../coreapi/linphonecore.c:3220 #, fuzzy msgid "Call aborted" msgstr "avbrytade" -#: ../coreapi/linphonecore.c:3685 +#: ../coreapi/linphonecore.c:3412 #, fuzzy msgid "Could not pause the call" msgstr "Kunde inte ringa" -#: ../coreapi/linphonecore.c:3690 +#: ../coreapi/linphonecore.c:3417 #, fuzzy msgid "Pausing the current call..." msgstr "Nuvarande samtal" @@ -1986,7 +1959,7 @@ msgstr "Förlopp" msgid "Unknown-bug" msgstr "Okänd bug" -#: ../coreapi/proxy.c:279 +#: ../coreapi/proxy.c:314 msgid "" "The sip proxy address you entered is invalid, it must start with \"sip:\" " "followed by a hostname." @@ -1994,7 +1967,7 @@ msgstr "" "SIP proxy adressen som du matade in är inte rätt, adressen måste starta med " "\"sip:\", följd av ett hostnamn" -#: ../coreapi/proxy.c:285 +#: ../coreapi/proxy.c:320 msgid "" "The sip identity you entered is invalid.\n" "It should look like sip:username@proxydomain, such as sip:alice@example.net" @@ -2002,134 +1975,159 @@ msgstr "" "SIP adressen som du matade in är inte rätt. Adressen borde se ut som sip:" "namn@domän, såsom sip:peter@exempel.se" -#: ../coreapi/proxy.c:1299 +#: ../coreapi/proxy.c:1369 #, c-format msgid "Could not login as %s" msgstr "Kunde inte logga in som %s" -#: ../coreapi/callbacks.c:354 +#: ../coreapi/callbacks.c:355 msgid "Remote ringing." msgstr "Ringer hos motparten." -#: ../coreapi/callbacks.c:370 +#: ../coreapi/callbacks.c:373 #, fuzzy msgid "Remote ringing..." msgstr "Ringer hos motparten." -#: ../coreapi/callbacks.c:381 +#: ../coreapi/callbacks.c:384 msgid "Early media." msgstr "Tidig media" -#: ../coreapi/callbacks.c:432 +#: ../coreapi/callbacks.c:435 #, fuzzy, c-format msgid "Call with %s is paused." msgstr "Samtal med %s" -#: ../coreapi/callbacks.c:445 +#: ../coreapi/callbacks.c:448 #, c-format msgid "Call answered by %s - on hold." msgstr "" -#: ../coreapi/callbacks.c:456 +#: ../coreapi/callbacks.c:459 #, fuzzy msgid "Call resumed." msgstr "Samtalet slut" -#: ../coreapi/callbacks.c:461 +#: ../coreapi/callbacks.c:464 #, c-format msgid "Call answered by %s." msgstr "" -#: ../coreapi/callbacks.c:480 +#: ../coreapi/callbacks.c:483 msgid "Incompatible, check codecs or security settings..." msgstr "" -#: ../coreapi/callbacks.c:531 +#: ../coreapi/callbacks.c:512 msgid "We have been resumed." msgstr "" -#: ../coreapi/callbacks.c:541 +#: ../coreapi/callbacks.c:521 msgid "We are paused by other party." msgstr "" -#: ../coreapi/callbacks.c:558 +#: ../coreapi/callbacks.c:556 msgid "Call is updated by remote." msgstr "" -#: ../coreapi/callbacks.c:637 +#: ../coreapi/callbacks.c:658 msgid "Call terminated." msgstr "Samtalet slut." -#: ../coreapi/callbacks.c:666 +#: ../coreapi/callbacks.c:687 msgid "User is busy." msgstr "Användare upptagen." -#: ../coreapi/callbacks.c:667 +#: ../coreapi/callbacks.c:688 msgid "User is temporarily unavailable." msgstr "Användaren temporärt inte tillgänglig." #. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:669 +#: ../coreapi/callbacks.c:690 msgid "User does not want to be disturbed." msgstr "Användaren vill inte bli störd." -#: ../coreapi/callbacks.c:670 +#: ../coreapi/callbacks.c:691 msgid "Call declined." msgstr "Samtalet avböjdes." -#: ../coreapi/callbacks.c:685 +#: ../coreapi/callbacks.c:706 msgid "Request timeout." msgstr "" -#: ../coreapi/callbacks.c:716 +#: ../coreapi/callbacks.c:737 #, fuzzy msgid "Redirected" msgstr "Omdirigerat till %s..." -#: ../coreapi/callbacks.c:766 +#: ../coreapi/callbacks.c:787 msgid "Incompatible media parameters." msgstr "" -#: ../coreapi/callbacks.c:777 +#: ../coreapi/callbacks.c:798 #, fuzzy msgid "Call failed." msgstr "Samtalet avböjdes." -#: ../coreapi/callbacks.c:852 +#: ../coreapi/callbacks.c:878 #, c-format msgid "Registration on %s successful." msgstr "Registrering hos %s lyckades." -#: ../coreapi/callbacks.c:853 +#: ../coreapi/callbacks.c:879 #, c-format msgid "Unregistration on %s done." msgstr "Avregistrering hos %s lyckades." -#: ../coreapi/callbacks.c:875 +#: ../coreapi/callbacks.c:897 msgid "no response timeout" msgstr "Inget svar inom angiven tid" -#: ../coreapi/callbacks.c:878 +#: ../coreapi/callbacks.c:900 #, c-format msgid "Registration on %s failed: %s" msgstr "Registrering hos %s mislyckades: %s" -#: ../coreapi/callbacks.c:885 +#: ../coreapi/callbacks.c:907 msgid "Service unavailable, retrying" msgstr "" -#: ../coreapi/linphonecall.c:175 +#: ../coreapi/linphonecall.c:177 #, fuzzy, c-format msgid "Authentication token is %s" msgstr "Linphone - Autentisering krävs" -#: ../coreapi/linphonecall.c:2994 +#: ../coreapi/linphonecall.c:2932 #, c-format msgid "You have missed %i call." msgid_plural "You have missed %i calls." msgstr[0] "Du har %i missat samtal" msgstr[1] "Du har %i missade samtal" +#~ msgid "aborted" +#~ msgstr "avbrytade" + +#~ msgid "completed" +#~ msgstr "avslutade" + +#~ msgid "missed" +#~ msgstr "missade" + +#~ msgid "" +#~ "%s at %s\n" +#~ "From: %s\n" +#~ "To: %s\n" +#~ "Status: %s\n" +#~ "Duration: %i mn %i sec\n" +#~ msgstr "" +#~ "%s på %s\n" +#~ "Från: %s\n" +#~ "Till: %s\n" +#~ "Status: %s\n" +#~ "Längd: %i min %i sek\n" + +#~ msgid "Outgoing call" +#~ msgstr "Utgående samtal" + #, fuzzy #~ msgid "No response." #~ msgstr "Inget svar inom angiven tid" diff --git a/po/zh_CN.po b/po/zh_CN.po index af5a7d776..c0eab3db4 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: linphone 3.3.2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-01 21:24+0200\n" +"POT-Creation-Date: 2014-09-15 09:24+0200\n" "PO-Revision-Date: 2011-01-08 23:51+0800\n" "Last-Translator: Aron Xu \n" "Language-Team: Chinese (simplified) \n" @@ -18,12 +18,12 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:973 +#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:974 #, c-format msgid "Call %s" msgstr "呼叫 %s" -#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:974 +#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:975 #, c-format msgid "Send text to %s" msgstr "发送消息给 %s" @@ -33,50 +33,50 @@ msgstr "发送消息给 %s" msgid "Recent calls (%i)" msgstr "正在呼叫" -#: ../gtk/calllogs.c:312 +#: ../gtk/calllogs.c:314 msgid "n/a" msgstr "" -#: ../gtk/calllogs.c:315 +#: ../gtk/calllogs.c:317 #, fuzzy msgid "Aborted" msgstr "中断" -#: ../gtk/calllogs.c:318 +#: ../gtk/calllogs.c:320 #, fuzzy msgid "Missed" msgstr "丢失" -#: ../gtk/calllogs.c:321 +#: ../gtk/calllogs.c:323 #, fuzzy msgid "Declined" msgstr "拒绝" -#: ../gtk/calllogs.c:327 +#: ../gtk/calllogs.c:329 #, c-format msgid "%i minute" msgid_plural "%i minutes" msgstr[0] "" -#: ../gtk/calllogs.c:330 +#: ../gtk/calllogs.c:332 #, c-format msgid "%i second" msgid_plural "%i seconds" msgstr[0] "" -#: ../gtk/calllogs.c:333 ../gtk/calllogs.c:339 +#: ../gtk/calllogs.c:335 ../gtk/calllogs.c:341 #, c-format msgid "%s\t%s" msgstr "" -#: ../gtk/calllogs.c:335 +#: ../gtk/calllogs.c:337 #, c-format msgid "" "%s\tQuality: %s\n" "%s\t%s\t" msgstr "" -#: ../gtk/calllogs.c:341 +#: ../gtk/calllogs.c:343 #, c-format msgid "" "%s\t\n" @@ -97,7 +97,7 @@ msgstr "静音" msgid "Couldn't find pixmap file: %s" msgstr "无法打开位图文件:%s" -#: ../gtk/chat.c:363 ../gtk/friendlist.c:923 +#: ../gtk/chat.c:364 ../gtk/friendlist.c:924 msgid "Invalid sip contact !" msgstr "无效的 SIP 联系人!" @@ -146,7 +146,7 @@ msgstr "帐户设置向导" msgid "Call with %s" msgstr "与 %s 通话" -#: ../gtk/main.c:1171 +#: ../gtk/main.c:1183 #, c-format msgid "" "%s would like to add you to his contact list.\n" @@ -158,68 +158,68 @@ msgstr "" "您是否允许他看到您的在线状态或者将它加为您的联系人允许?\n" "如果您回答否,则会将该人临时性的放入黑名单" -#: ../gtk/main.c:1248 +#: ../gtk/main.c:1260 #, fuzzy, c-format msgid "" "Please enter your password for username %s\n" " at realm %s:" msgstr "请输入 %s@%s 的密码:" -#: ../gtk/main.c:1364 +#: ../gtk/main.c:1376 #, fuzzy msgid "Call error" msgstr "呼叫历史" -#: ../gtk/main.c:1367 ../coreapi/linphonecore.c:3515 +#: ../gtk/main.c:1379 ../coreapi/linphonecore.c:3240 msgid "Call ended" msgstr "呼叫结束" -#: ../gtk/main.c:1370 ../coreapi/linphonecore.c:254 +#: ../gtk/main.c:1382 msgid "Incoming call" msgstr "呼入" -#: ../gtk/main.c:1372 ../gtk/incall_view.c:513 ../gtk/main.ui.h:5 +#: ../gtk/main.c:1384 ../gtk/incall_view.c:522 ../gtk/main.ui.h:5 msgid "Answer" msgstr "" -#: ../gtk/main.c:1374 ../gtk/main.ui.h:6 +#: ../gtk/main.c:1386 ../gtk/main.ui.h:6 msgid "Decline" msgstr "拒绝" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy msgid "Call paused" msgstr "中断" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy, c-format msgid "by %s" msgstr "端口" -#: ../gtk/main.c:1447 +#: ../gtk/main.c:1459 #, c-format msgid "%s proposed to start video. Do you accept ?" msgstr "" -#: ../gtk/main.c:1609 +#: ../gtk/main.c:1621 msgid "Website link" msgstr "网站" -#: ../gtk/main.c:1658 +#: ../gtk/main.c:1670 msgid "Linphone - a video internet phone" msgstr "Linphone - 互联网视频电话" -#: ../gtk/main.c:1750 +#: ../gtk/main.c:1762 #, c-format msgid "%s (Default)" msgstr "%s (默认)" -#: ../gtk/main.c:2086 ../coreapi/callbacks.c:927 +#: ../gtk/main.c:2099 ../coreapi/callbacks.c:949 #, c-format msgid "We are transferred to %s" msgstr "" -#: ../gtk/main.c:2096 +#: ../gtk/main.c:2109 msgid "" "No sound cards have been detected on this computer.\n" "You won't be able to send or receive audio calls." @@ -227,7 +227,7 @@ msgstr "" "未在此计算机上检测到声卡。\n" "您无法发送或接收音频呼叫。" -#: ../gtk/main.c:2237 +#: ../gtk/main.c:2250 msgid "A free SIP video-phone" msgstr "免费的 SIP 视频电话" @@ -239,7 +239,7 @@ msgstr "" msgid "Presence status" msgstr "在线状态" -#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:550 ../gtk/contact.ui.h:1 +#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:552 ../gtk/contact.ui.h:1 msgid "Name" msgstr "名称" @@ -257,141 +257,141 @@ msgstr "" msgid "Search in %s directory" msgstr "在 %s 目录中查找 " -#: ../gtk/friendlist.c:975 +#: ../gtk/friendlist.c:976 #, c-format msgid "Edit contact '%s'" msgstr "编辑联系人 %s" -#: ../gtk/friendlist.c:976 +#: ../gtk/friendlist.c:977 #, c-format msgid "Delete contact '%s'" msgstr "删除联系人 %s" -#: ../gtk/friendlist.c:977 +#: ../gtk/friendlist.c:978 #, fuzzy, c-format msgid "Delete chat history of '%s'" msgstr "删除联系人 %s" -#: ../gtk/friendlist.c:1028 +#: ../gtk/friendlist.c:1029 #, c-format msgid "Add new contact from %s directory" msgstr "从 %s 目录增加联系人 " -#: ../gtk/propertybox.c:556 +#: ../gtk/propertybox.c:558 msgid "Rate (Hz)" msgstr "采样率(Hz)" -#: ../gtk/propertybox.c:562 +#: ../gtk/propertybox.c:564 msgid "Status" msgstr "状态" -#: ../gtk/propertybox.c:568 +#: ../gtk/propertybox.c:570 #, fuzzy msgid "IP Bitrate (kbit/s)" msgstr "最小比特率(kbit/s)" -#: ../gtk/propertybox.c:575 +#: ../gtk/propertybox.c:577 msgid "Parameters" msgstr "参数" -#: ../gtk/propertybox.c:618 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:763 msgid "Enabled" msgstr "启用" -#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:622 ../gtk/propertybox.c:763 msgid "Disabled" msgstr "禁用" -#: ../gtk/propertybox.c:807 +#: ../gtk/propertybox.c:809 msgid "Account" msgstr "帐户" -#: ../gtk/propertybox.c:1061 +#: ../gtk/propertybox.c:1063 msgid "English" msgstr "英语" -#: ../gtk/propertybox.c:1062 +#: ../gtk/propertybox.c:1064 msgid "French" msgstr "法语" -#: ../gtk/propertybox.c:1063 +#: ../gtk/propertybox.c:1065 msgid "Swedish" msgstr "瑞典语" -#: ../gtk/propertybox.c:1064 +#: ../gtk/propertybox.c:1066 msgid "Italian" msgstr "意大利语" -#: ../gtk/propertybox.c:1065 +#: ../gtk/propertybox.c:1067 msgid "Spanish" msgstr "西班牙语" -#: ../gtk/propertybox.c:1066 +#: ../gtk/propertybox.c:1068 msgid "Brazilian Portugese" msgstr "巴西葡萄牙语" -#: ../gtk/propertybox.c:1067 +#: ../gtk/propertybox.c:1069 msgid "Polish" msgstr "波兰语" -#: ../gtk/propertybox.c:1068 +#: ../gtk/propertybox.c:1070 msgid "German" msgstr "德语" -#: ../gtk/propertybox.c:1069 +#: ../gtk/propertybox.c:1071 msgid "Russian" msgstr "俄语" -#: ../gtk/propertybox.c:1070 +#: ../gtk/propertybox.c:1072 msgid "Japanese" msgstr "日语" -#: ../gtk/propertybox.c:1071 +#: ../gtk/propertybox.c:1073 msgid "Dutch" msgstr "荷兰语" -#: ../gtk/propertybox.c:1072 +#: ../gtk/propertybox.c:1074 msgid "Hungarian" msgstr "匈牙利语" -#: ../gtk/propertybox.c:1073 +#: ../gtk/propertybox.c:1075 msgid "Czech" msgstr "捷克语" -#: ../gtk/propertybox.c:1074 +#: ../gtk/propertybox.c:1076 msgid "Chinese" msgstr "中文" -#: ../gtk/propertybox.c:1075 +#: ../gtk/propertybox.c:1077 msgid "Traditional Chinese" msgstr "" -#: ../gtk/propertybox.c:1076 +#: ../gtk/propertybox.c:1078 msgid "Norwegian" msgstr "" -#: ../gtk/propertybox.c:1077 +#: ../gtk/propertybox.c:1079 msgid "Hebrew" msgstr "" -#: ../gtk/propertybox.c:1078 +#: ../gtk/propertybox.c:1080 msgid "Serbian" msgstr "" -#: ../gtk/propertybox.c:1145 +#: ../gtk/propertybox.c:1147 msgid "" "You need to restart linphone for the new language selection to take effect." msgstr "您需要重启 linphone 以使语言选择生效。" -#: ../gtk/propertybox.c:1223 +#: ../gtk/propertybox.c:1225 msgid "None" msgstr "" -#: ../gtk/propertybox.c:1227 +#: ../gtk/propertybox.c:1229 msgid "SRTP" msgstr "" -#: ../gtk/propertybox.c:1233 +#: ../gtk/propertybox.c:1235 msgid "ZRTP" msgstr "" @@ -465,110 +465,114 @@ msgstr "" msgid "Enter your linphone.org username" msgstr "" -#: ../gtk/setupwizard.c:96 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 +#: ../gtk/setupwizard.c:102 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 msgid "Username:" msgstr "用户名:" -#: ../gtk/setupwizard.c:98 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 +#: ../gtk/setupwizard.c:104 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 msgid "Password:" msgstr "密码:" -#: ../gtk/setupwizard.c:118 +#: ../gtk/setupwizard.c:124 msgid "Enter your account informations" msgstr "" -#: ../gtk/setupwizard.c:125 +#: ../gtk/setupwizard.c:140 #, fuzzy msgid "Username*" msgstr "用户名" -#: ../gtk/setupwizard.c:126 +#: ../gtk/setupwizard.c:141 #, fuzzy msgid "Password*" msgstr "密码" -#: ../gtk/setupwizard.c:129 +#: ../gtk/setupwizard.c:144 msgid "Domain*" msgstr "" -#: ../gtk/setupwizard.c:130 +#: ../gtk/setupwizard.c:145 msgid "Proxy" msgstr "" -#: ../gtk/setupwizard.c:302 +#: ../gtk/setupwizard.c:317 msgid "(*) Required fields" msgstr "" -#: ../gtk/setupwizard.c:303 +#: ../gtk/setupwizard.c:318 #, fuzzy msgid "Username: (*)" msgstr "用户名:" -#: ../gtk/setupwizard.c:305 +#: ../gtk/setupwizard.c:320 #, fuzzy msgid "Password: (*)" msgstr "密码:" -#: ../gtk/setupwizard.c:307 +#: ../gtk/setupwizard.c:322 msgid "Email: (*)" msgstr "" -#: ../gtk/setupwizard.c:309 +#: ../gtk/setupwizard.c:324 msgid "Confirm your password: (*)" msgstr "" -#: ../gtk/setupwizard.c:373 +#: ../gtk/setupwizard.c:338 +msgid "Keep me informed with linphone updates" +msgstr "" + +#: ../gtk/setupwizard.c:394 msgid "" "Error, account not validated, username already used or server unreachable.\n" "Please go back and try again." msgstr "" -#: ../gtk/setupwizard.c:384 +#: ../gtk/setupwizard.c:405 msgid "Thank you. Your account is now configured and ready for use." msgstr "谢谢,您的帐户已经配置完毕,可以使用。" -#: ../gtk/setupwizard.c:392 +#: ../gtk/setupwizard.c:413 msgid "" "Please validate your account by clicking on the link we just sent you by " "email.\n" "Then come back here and press Next button." msgstr "" -#: ../gtk/setupwizard.c:564 +#: ../gtk/setupwizard.c:600 #, fuzzy msgid "SIP account configuration assistant" msgstr "帐户设置向导" -#: ../gtk/setupwizard.c:582 +#: ../gtk/setupwizard.c:618 msgid "Welcome to the account setup assistant" msgstr "欢迎使用帐户设置向导" -#: ../gtk/setupwizard.c:587 +#: ../gtk/setupwizard.c:623 msgid "Account setup assistant" msgstr "帐户设置向导" -#: ../gtk/setupwizard.c:593 +#: ../gtk/setupwizard.c:629 #, fuzzy msgid "Configure your account (step 1/1)" msgstr "配置 SIP 帐户" -#: ../gtk/setupwizard.c:598 +#: ../gtk/setupwizard.c:634 msgid "Enter your sip username (step 1/1)" msgstr "" -#: ../gtk/setupwizard.c:602 +#: ../gtk/setupwizard.c:638 msgid "Enter account information (step 1/2)" msgstr "" -#: ../gtk/setupwizard.c:611 +#: ../gtk/setupwizard.c:647 msgid "Validation (step 2/2)" msgstr "" -#: ../gtk/setupwizard.c:616 +#: ../gtk/setupwizard.c:652 msgid "Error" msgstr "" -#: ../gtk/setupwizard.c:620 ../gtk/audio_assistant.c:519 +#: ../gtk/setupwizard.c:656 ../gtk/audio_assistant.c:527 #, fuzzy msgid "Terminating" msgstr "终止呼叫" @@ -640,133 +644,133 @@ msgstr "ICE 过滤器" msgid "Direct or through server" msgstr "" -#: ../gtk/incall_view.c:266 ../gtk/incall_view.c:276 +#: ../gtk/incall_view.c:267 ../gtk/incall_view.c:279 #, c-format msgid "" "download: %f\n" "upload: %f (kbit/s)" msgstr "" -#: ../gtk/incall_view.c:271 ../gtk/incall_view.c:272 +#: ../gtk/incall_view.c:272 ../gtk/incall_view.c:274 #, c-format -msgid "%ix%i" +msgid "%ix%i @ %f fps" msgstr "" -#: ../gtk/incall_view.c:301 +#: ../gtk/incall_view.c:304 #, c-format msgid "%.3f seconds" msgstr "" -#: ../gtk/incall_view.c:399 ../gtk/main.ui.h:12 +#: ../gtk/incall_view.c:407 ../gtk/main.ui.h:12 msgid "Hang up" msgstr "" -#: ../gtk/incall_view.c:492 +#: ../gtk/incall_view.c:501 msgid "Calling..." msgstr "正在呼叫..." -#: ../gtk/incall_view.c:495 ../gtk/incall_view.c:698 +#: ../gtk/incall_view.c:504 ../gtk/incall_view.c:707 msgid "00::00::00" msgstr "00::00::00" -#: ../gtk/incall_view.c:506 +#: ../gtk/incall_view.c:515 #, fuzzy msgid "Incoming call" msgstr "呼入" -#: ../gtk/incall_view.c:543 +#: ../gtk/incall_view.c:552 msgid "good" msgstr "" -#: ../gtk/incall_view.c:545 +#: ../gtk/incall_view.c:554 msgid "average" msgstr "" -#: ../gtk/incall_view.c:547 +#: ../gtk/incall_view.c:556 msgid "poor" msgstr "" -#: ../gtk/incall_view.c:549 +#: ../gtk/incall_view.c:558 msgid "very poor" msgstr "" -#: ../gtk/incall_view.c:551 +#: ../gtk/incall_view.c:560 msgid "too bad" msgstr "" -#: ../gtk/incall_view.c:552 ../gtk/incall_view.c:568 +#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:577 msgid "unavailable" msgstr "" -#: ../gtk/incall_view.c:660 +#: ../gtk/incall_view.c:669 msgid "Secured by SRTP" msgstr "" -#: ../gtk/incall_view.c:666 +#: ../gtk/incall_view.c:675 #, c-format msgid "Secured by ZRTP - [auth token: %s]" msgstr "" -#: ../gtk/incall_view.c:672 +#: ../gtk/incall_view.c:681 msgid "Set unverified" msgstr "" -#: ../gtk/incall_view.c:672 ../gtk/main.ui.h:4 +#: ../gtk/incall_view.c:681 ../gtk/main.ui.h:4 msgid "Set verified" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In conference" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 #, fuzzy msgid "In call" msgstr "正在呼叫" -#: ../gtk/incall_view.c:729 +#: ../gtk/incall_view.c:738 #, fuzzy msgid "Paused call" msgstr "正在呼叫" -#: ../gtk/incall_view.c:742 +#: ../gtk/incall_view.c:751 #, c-format msgid "%02i::%02i::%02i" msgstr "%02i::%02i::%02i" -#: ../gtk/incall_view.c:760 +#: ../gtk/incall_view.c:772 msgid "Call ended." msgstr "通话结束。" -#: ../gtk/incall_view.c:791 +#: ../gtk/incall_view.c:803 msgid "Transfer in progress" msgstr "" -#: ../gtk/incall_view.c:794 +#: ../gtk/incall_view.c:806 msgid "Transfer done." msgstr "" -#: ../gtk/incall_view.c:797 +#: ../gtk/incall_view.c:809 #, fuzzy msgid "Transfer failed." msgstr "呼叫失败。" -#: ../gtk/incall_view.c:841 +#: ../gtk/incall_view.c:853 msgid "Resume" msgstr "" -#: ../gtk/incall_view.c:848 ../gtk/main.ui.h:9 +#: ../gtk/incall_view.c:860 ../gtk/main.ui.h:9 msgid "Pause" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, c-format msgid "" "Recording into\n" "%s %s" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 msgid "(Paused)" msgstr "" @@ -801,7 +805,7 @@ msgstr "" msgid "Too loud" msgstr "" -#: ../gtk/audio_assistant.c:316 +#: ../gtk/audio_assistant.c:318 #, fuzzy msgid "" "Welcome !\n" @@ -810,59 +814,59 @@ msgstr "" "欢迎使用 Linphone!\n" "设置向导将帮助您配置打网络电话的 SIP 帐户。" -#: ../gtk/audio_assistant.c:326 +#: ../gtk/audio_assistant.c:328 #, fuzzy msgid "Capture device" msgstr "录音设备:" -#: ../gtk/audio_assistant.c:327 +#: ../gtk/audio_assistant.c:329 msgid "Recorded volume" msgstr "" -#: ../gtk/audio_assistant.c:331 +#: ../gtk/audio_assistant.c:333 msgid "No voice" msgstr "" -#: ../gtk/audio_assistant.c:367 +#: ../gtk/audio_assistant.c:369 #, fuzzy msgid "Playback device" msgstr "回放设备:" -#: ../gtk/audio_assistant.c:368 +#: ../gtk/audio_assistant.c:370 msgid "Play three beeps" msgstr "" -#: ../gtk/audio_assistant.c:400 +#: ../gtk/audio_assistant.c:403 msgid "Press the record button and say some words" msgstr "" -#: ../gtk/audio_assistant.c:401 +#: ../gtk/audio_assistant.c:404 msgid "Listen to your record voice" msgstr "" -#: ../gtk/audio_assistant.c:430 +#: ../gtk/audio_assistant.c:433 msgid "Let's start Linphone now" msgstr "" -#: ../gtk/audio_assistant.c:488 +#: ../gtk/audio_assistant.c:496 #, fuzzy msgid "Audio Assistant" msgstr "配置向导" -#: ../gtk/audio_assistant.c:498 ../gtk/main.ui.h:31 +#: ../gtk/audio_assistant.c:506 ../gtk/main.ui.h:31 #, fuzzy msgid "Audio assistant" msgstr "帐户设置向导" -#: ../gtk/audio_assistant.c:503 +#: ../gtk/audio_assistant.c:511 msgid "Mic Gain calibration" msgstr "" -#: ../gtk/audio_assistant.c:509 +#: ../gtk/audio_assistant.c:517 msgid "Speaker volume calibration" msgstr "" -#: ../gtk/audio_assistant.c:514 +#: ../gtk/audio_assistant.c:522 msgid "Record and Play" msgstr "" @@ -1840,99 +1844,68 @@ msgstr "正在连接..." msgid "Please wait while fetching configuration from server..." msgstr "" -#: ../coreapi/linphonecore.c:242 -msgid "aborted" -msgstr "中断" - -#: ../coreapi/linphonecore.c:245 -msgid "completed" -msgstr "完成" - -#: ../coreapi/linphonecore.c:248 -msgid "missed" -msgstr "丢失" - -#: ../coreapi/linphonecore.c:253 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" -"%s @ %s\n" -"主叫:%s\n" -"被叫: %s\n" -"状态:%s\n" -"状态:%i 分 %i 秒\n" - -#: ../coreapi/linphonecore.c:254 -msgid "Outgoing call" -msgstr "呼出" - -#: ../coreapi/linphonecore.c:1287 +#: ../coreapi/linphonecore.c:1034 msgid "Ready" msgstr "就绪" -#: ../coreapi/linphonecore.c:2248 +#: ../coreapi/linphonecore.c:1967 #, fuzzy msgid "Configuring" msgstr "确认" -#: ../coreapi/linphonecore.c:2410 +#: ../coreapi/linphonecore.c:2133 msgid "Looking for telephone number destination..." msgstr "查询电话号码目的地..." -#: ../coreapi/linphonecore.c:2413 +#: ../coreapi/linphonecore.c:2136 msgid "Could not resolve this number." msgstr "该号码无法解析。" #. must be known at that time -#: ../coreapi/linphonecore.c:2695 +#: ../coreapi/linphonecore.c:2418 msgid "Contacting" msgstr "联系中" -#: ../coreapi/linphonecore.c:2702 +#: ../coreapi/linphonecore.c:2425 #, fuzzy msgid "Could not call" msgstr "无法呼叫" -#: ../coreapi/linphonecore.c:2852 +#: ../coreapi/linphonecore.c:2576 msgid "Sorry, we have reached the maximum number of simultaneous calls" msgstr "" -#: ../coreapi/linphonecore.c:3022 +#: ../coreapi/linphonecore.c:2745 msgid "is contacting you" msgstr "正在联系您" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid " and asked autoanswer." msgstr " 并询问了自动回答。" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid "." msgstr "." -#: ../coreapi/linphonecore.c:3139 +#: ../coreapi/linphonecore.c:2865 msgid "Modifying call parameters..." msgstr "" -#: ../coreapi/linphonecore.c:3469 +#: ../coreapi/linphonecore.c:3194 msgid "Connected." msgstr "已连接。" -#: ../coreapi/linphonecore.c:3495 +#: ../coreapi/linphonecore.c:3220 #, fuzzy msgid "Call aborted" msgstr "中断" -#: ../coreapi/linphonecore.c:3685 +#: ../coreapi/linphonecore.c:3412 #, fuzzy msgid "Could not pause the call" msgstr "无法呼叫" -#: ../coreapi/linphonecore.c:3690 +#: ../coreapi/linphonecore.c:3417 msgid "Pausing the current call..." msgstr "" @@ -1997,13 +1970,13 @@ msgstr "通话时间" msgid "Unknown-bug" msgstr "未知错误" -#: ../coreapi/proxy.c:279 +#: ../coreapi/proxy.c:314 msgid "" "The sip proxy address you entered is invalid, it must start with \"sip:\" " "followed by a hostname." msgstr "您输入的 SIP 代理地址无效,它必须是以“sip:”开头,并紧随一个主机名。" -#: ../coreapi/proxy.c:285 +#: ../coreapi/proxy.c:320 msgid "" "The sip identity you entered is invalid.\n" "It should look like sip:username@proxydomain, such as sip:alice@example.net" @@ -2011,131 +1984,156 @@ msgstr "" "您输入的地址无效。\n" "它应具有“sip:用户名@代理域”的形式,例如 sip:alice@example.net" -#: ../coreapi/proxy.c:1299 +#: ../coreapi/proxy.c:1369 #, c-format msgid "Could not login as %s" msgstr "无法登录为 %s" -#: ../coreapi/callbacks.c:354 +#: ../coreapi/callbacks.c:355 msgid "Remote ringing." msgstr "响铃。" -#: ../coreapi/callbacks.c:370 +#: ../coreapi/callbacks.c:373 #, fuzzy msgid "Remote ringing..." msgstr "响铃。" -#: ../coreapi/callbacks.c:381 +#: ../coreapi/callbacks.c:384 msgid "Early media." msgstr "" -#: ../coreapi/callbacks.c:432 +#: ../coreapi/callbacks.c:435 #, fuzzy, c-format msgid "Call with %s is paused." msgstr "与 %s 通话" -#: ../coreapi/callbacks.c:445 +#: ../coreapi/callbacks.c:448 #, c-format msgid "Call answered by %s - on hold." msgstr "" -#: ../coreapi/callbacks.c:456 +#: ../coreapi/callbacks.c:459 #, fuzzy msgid "Call resumed." msgstr "呼叫结束" -#: ../coreapi/callbacks.c:461 +#: ../coreapi/callbacks.c:464 #, c-format msgid "Call answered by %s." msgstr "" -#: ../coreapi/callbacks.c:480 +#: ../coreapi/callbacks.c:483 msgid "Incompatible, check codecs or security settings..." msgstr "" -#: ../coreapi/callbacks.c:531 +#: ../coreapi/callbacks.c:512 msgid "We have been resumed." msgstr "" -#: ../coreapi/callbacks.c:541 +#: ../coreapi/callbacks.c:521 msgid "We are paused by other party." msgstr "" -#: ../coreapi/callbacks.c:558 +#: ../coreapi/callbacks.c:556 msgid "Call is updated by remote." msgstr "" -#: ../coreapi/callbacks.c:637 +#: ../coreapi/callbacks.c:658 msgid "Call terminated." msgstr "通话结束。" -#: ../coreapi/callbacks.c:666 +#: ../coreapi/callbacks.c:687 msgid "User is busy." msgstr "被叫正忙。" -#: ../coreapi/callbacks.c:667 +#: ../coreapi/callbacks.c:688 msgid "User is temporarily unavailable." msgstr "您呼叫的用户暂时无法接通。" #. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:669 +#: ../coreapi/callbacks.c:690 msgid "User does not want to be disturbed." msgstr "用户已开启免打扰功能。" -#: ../coreapi/callbacks.c:670 +#: ../coreapi/callbacks.c:691 msgid "Call declined." msgstr "呼叫被拒绝。" -#: ../coreapi/callbacks.c:685 +#: ../coreapi/callbacks.c:706 msgid "Request timeout." msgstr "" -#: ../coreapi/callbacks.c:716 +#: ../coreapi/callbacks.c:737 msgid "Redirected" msgstr "已重定向" -#: ../coreapi/callbacks.c:766 +#: ../coreapi/callbacks.c:787 msgid "Incompatible media parameters." msgstr "" -#: ../coreapi/callbacks.c:777 +#: ../coreapi/callbacks.c:798 msgid "Call failed." msgstr "呼叫失败。" -#: ../coreapi/callbacks.c:852 +#: ../coreapi/callbacks.c:878 #, c-format msgid "Registration on %s successful." msgstr "成功注册到 %s" -#: ../coreapi/callbacks.c:853 +#: ../coreapi/callbacks.c:879 #, c-format msgid "Unregistration on %s done." msgstr "已在 %s 解除注册。" -#: ../coreapi/callbacks.c:875 +#: ../coreapi/callbacks.c:897 msgid "no response timeout" msgstr "没有响应,超时" -#: ../coreapi/callbacks.c:878 +#: ../coreapi/callbacks.c:900 #, c-format msgid "Registration on %s failed: %s" msgstr "注册到 %s 失败: %s" -#: ../coreapi/callbacks.c:885 +#: ../coreapi/callbacks.c:907 msgid "Service unavailable, retrying" msgstr "" -#: ../coreapi/linphonecall.c:175 +#: ../coreapi/linphonecall.c:177 #, fuzzy, c-format msgid "Authentication token is %s" msgstr "Linphone - 需要认证" -#: ../coreapi/linphonecall.c:2994 +#: ../coreapi/linphonecall.c:2932 #, c-format msgid "You have missed %i call." msgid_plural "You have missed %i calls." msgstr[0] "您错过了 %i 个呼叫。" +#~ msgid "aborted" +#~ msgstr "中断" + +#~ msgid "completed" +#~ msgstr "完成" + +#~ msgid "missed" +#~ msgstr "丢失" + +#~ msgid "" +#~ "%s at %s\n" +#~ "From: %s\n" +#~ "To: %s\n" +#~ "Status: %s\n" +#~ "Duration: %i mn %i sec\n" +#~ msgstr "" +#~ "%s @ %s\n" +#~ "主叫:%s\n" +#~ "被叫: %s\n" +#~ "状态:%s\n" +#~ "状态:%i 分 %i 秒\n" + +#~ msgid "Outgoing call" +#~ msgstr "呼出" + #~ msgid "No response." #~ msgstr "没有响应。" diff --git a/po/zh_TW.po b/po/zh_TW.po index e44590a16..789c278d5 100644 --- a/po/zh_TW.po +++ b/po/zh_TW.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: linphone 3.4\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2014-07-01 21:24+0200\n" +"POT-Creation-Date: 2014-09-15 09:24+0200\n" "PO-Revision-Date: 2011-04-06 21:24+0800\n" "Last-Translator: Chao-Hsiung Liao \n" "Language-Team: \n" @@ -17,12 +17,12 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:973 +#: ../gtk/calllogs.c:148 ../gtk/friendlist.c:974 #, c-format msgid "Call %s" msgstr "播打給 %s" -#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:974 +#: ../gtk/calllogs.c:149 ../gtk/friendlist.c:975 #, c-format msgid "Send text to %s" msgstr "傳送文字給 %s" @@ -32,50 +32,50 @@ msgstr "傳送文字給 %s" msgid "Recent calls (%i)" msgstr "通話中" -#: ../gtk/calllogs.c:312 +#: ../gtk/calllogs.c:314 msgid "n/a" msgstr "" -#: ../gtk/calllogs.c:315 +#: ../gtk/calllogs.c:317 #, fuzzy msgid "Aborted" msgstr "已放棄" -#: ../gtk/calllogs.c:318 +#: ../gtk/calllogs.c:320 #, fuzzy msgid "Missed" msgstr "未接" -#: ../gtk/calllogs.c:321 +#: ../gtk/calllogs.c:323 #, fuzzy msgid "Declined" msgstr "拒接" -#: ../gtk/calllogs.c:327 +#: ../gtk/calllogs.c:329 #, c-format msgid "%i minute" msgid_plural "%i minutes" msgstr[0] "" -#: ../gtk/calllogs.c:330 +#: ../gtk/calllogs.c:332 #, c-format msgid "%i second" msgid_plural "%i seconds" msgstr[0] "" -#: ../gtk/calllogs.c:333 ../gtk/calllogs.c:339 +#: ../gtk/calllogs.c:335 ../gtk/calllogs.c:341 #, c-format msgid "%s\t%s" msgstr "" -#: ../gtk/calllogs.c:335 +#: ../gtk/calllogs.c:337 #, c-format msgid "" "%s\tQuality: %s\n" "%s\t%s\t" msgstr "" -#: ../gtk/calllogs.c:341 +#: ../gtk/calllogs.c:343 #, c-format msgid "" "%s\t\n" @@ -96,7 +96,7 @@ msgstr "靜音" msgid "Couldn't find pixmap file: %s" msgstr "找不到 pixmap 檔:%s" -#: ../gtk/chat.c:363 ../gtk/friendlist.c:923 +#: ../gtk/chat.c:364 ../gtk/friendlist.c:924 msgid "Invalid sip contact !" msgstr "無效的 sip 連絡人!" @@ -146,7 +146,7 @@ msgstr "帳號設定助理" msgid "Call with %s" msgstr "和 %s 通話" -#: ../gtk/main.c:1171 +#: ../gtk/main.c:1183 #, c-format msgid "" "%s would like to add you to his contact list.\n" @@ -158,7 +158,7 @@ msgstr "" "您是否要允許他看見您的上線狀態或將他加入您的連絡人清單?\n" "如果您回答否,這個人會被暫時列入黑名單。" -#: ../gtk/main.c:1248 +#: ../gtk/main.c:1260 #, fuzzy, c-format msgid "" "Please enter your password for username %s\n" @@ -167,61 +167,61 @@ msgstr "" "請輸入您使用者名稱 %s\n" "於網域 %s 的密碼:" -#: ../gtk/main.c:1364 +#: ../gtk/main.c:1376 #, fuzzy msgid "Call error" msgstr "通話紀錄" -#: ../gtk/main.c:1367 ../coreapi/linphonecore.c:3515 +#: ../gtk/main.c:1379 ../coreapi/linphonecore.c:3240 msgid "Call ended" msgstr "通話已結束" -#: ../gtk/main.c:1370 ../coreapi/linphonecore.c:254 +#: ../gtk/main.c:1382 msgid "Incoming call" msgstr "來電" -#: ../gtk/main.c:1372 ../gtk/incall_view.c:513 ../gtk/main.ui.h:5 +#: ../gtk/main.c:1384 ../gtk/incall_view.c:522 ../gtk/main.ui.h:5 msgid "Answer" msgstr "接聽" -#: ../gtk/main.c:1374 ../gtk/main.ui.h:6 +#: ../gtk/main.c:1386 ../gtk/main.ui.h:6 msgid "Decline" msgstr "拒接" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy msgid "Call paused" msgstr "通話已放棄" -#: ../gtk/main.c:1380 +#: ../gtk/main.c:1392 #, fuzzy, c-format msgid "by %s" msgstr "連接埠" -#: ../gtk/main.c:1447 +#: ../gtk/main.c:1459 #, c-format msgid "%s proposed to start video. Do you accept ?" msgstr "" -#: ../gtk/main.c:1609 +#: ../gtk/main.c:1621 msgid "Website link" msgstr "網站連結" -#: ../gtk/main.c:1658 +#: ../gtk/main.c:1670 msgid "Linphone - a video internet phone" msgstr "Linphone - 網路視訊電話" -#: ../gtk/main.c:1750 +#: ../gtk/main.c:1762 #, c-format msgid "%s (Default)" msgstr "%s (預設值)" -#: ../gtk/main.c:2086 ../coreapi/callbacks.c:927 +#: ../gtk/main.c:2099 ../coreapi/callbacks.c:949 #, c-format msgid "We are transferred to %s" msgstr "我們被轉接到 %s" -#: ../gtk/main.c:2096 +#: ../gtk/main.c:2109 msgid "" "No sound cards have been detected on this computer.\n" "You won't be able to send or receive audio calls." @@ -229,7 +229,7 @@ msgstr "" "在這臺電腦中偵測不到音效卡。\n" "您將無法傳送或接收語音電話。" -#: ../gtk/main.c:2237 +#: ../gtk/main.c:2250 msgid "A free SIP video-phone" msgstr "自由的 SIP 視訊電話" @@ -241,7 +241,7 @@ msgstr "" msgid "Presence status" msgstr "上線狀態" -#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:550 ../gtk/contact.ui.h:1 +#: ../gtk/friendlist.c:709 ../gtk/propertybox.c:552 ../gtk/contact.ui.h:1 msgid "Name" msgstr "名稱" @@ -259,141 +259,141 @@ msgstr "" msgid "Search in %s directory" msgstr "在 %s 目錄中搜尋" -#: ../gtk/friendlist.c:975 +#: ../gtk/friendlist.c:976 #, c-format msgid "Edit contact '%s'" msgstr "編輯連絡人「%s」" -#: ../gtk/friendlist.c:976 +#: ../gtk/friendlist.c:977 #, c-format msgid "Delete contact '%s'" msgstr "刪除連絡人「%s」" -#: ../gtk/friendlist.c:977 +#: ../gtk/friendlist.c:978 #, fuzzy, c-format msgid "Delete chat history of '%s'" msgstr "刪除連絡人「%s」" -#: ../gtk/friendlist.c:1028 +#: ../gtk/friendlist.c:1029 #, c-format msgid "Add new contact from %s directory" msgstr "從 %s 目錄加入新的連絡人" -#: ../gtk/propertybox.c:556 +#: ../gtk/propertybox.c:558 msgid "Rate (Hz)" msgstr "頻率 (Hz)" -#: ../gtk/propertybox.c:562 +#: ../gtk/propertybox.c:564 msgid "Status" msgstr "狀態" -#: ../gtk/propertybox.c:568 +#: ../gtk/propertybox.c:570 #, fuzzy msgid "IP Bitrate (kbit/s)" msgstr "最小頻寬 (kbit/s)" -#: ../gtk/propertybox.c:575 +#: ../gtk/propertybox.c:577 msgid "Parameters" msgstr "參數" -#: ../gtk/propertybox.c:618 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:763 msgid "Enabled" msgstr "已啟用" -#: ../gtk/propertybox.c:620 ../gtk/propertybox.c:761 +#: ../gtk/propertybox.c:622 ../gtk/propertybox.c:763 msgid "Disabled" msgstr "已停用" -#: ../gtk/propertybox.c:807 +#: ../gtk/propertybox.c:809 msgid "Account" msgstr "帳號" -#: ../gtk/propertybox.c:1061 +#: ../gtk/propertybox.c:1063 msgid "English" msgstr "英語" -#: ../gtk/propertybox.c:1062 +#: ../gtk/propertybox.c:1064 msgid "French" msgstr "法語" -#: ../gtk/propertybox.c:1063 +#: ../gtk/propertybox.c:1065 msgid "Swedish" msgstr "瑞典語" -#: ../gtk/propertybox.c:1064 +#: ../gtk/propertybox.c:1066 msgid "Italian" msgstr "義大利語" -#: ../gtk/propertybox.c:1065 +#: ../gtk/propertybox.c:1067 msgid "Spanish" msgstr "西班牙語" -#: ../gtk/propertybox.c:1066 +#: ../gtk/propertybox.c:1068 msgid "Brazilian Portugese" msgstr "巴西葡萄牙語" -#: ../gtk/propertybox.c:1067 +#: ../gtk/propertybox.c:1069 msgid "Polish" msgstr "波蘭語" -#: ../gtk/propertybox.c:1068 +#: ../gtk/propertybox.c:1070 msgid "German" msgstr "德語" -#: ../gtk/propertybox.c:1069 +#: ../gtk/propertybox.c:1071 msgid "Russian" msgstr "俄語" -#: ../gtk/propertybox.c:1070 +#: ../gtk/propertybox.c:1072 msgid "Japanese" msgstr "日語" -#: ../gtk/propertybox.c:1071 +#: ../gtk/propertybox.c:1073 msgid "Dutch" msgstr "荷蘭語" -#: ../gtk/propertybox.c:1072 +#: ../gtk/propertybox.c:1074 msgid "Hungarian" msgstr "匈牙利語" -#: ../gtk/propertybox.c:1073 +#: ../gtk/propertybox.c:1075 msgid "Czech" msgstr "捷克語" -#: ../gtk/propertybox.c:1074 +#: ../gtk/propertybox.c:1076 msgid "Chinese" msgstr "中文" -#: ../gtk/propertybox.c:1075 +#: ../gtk/propertybox.c:1077 msgid "Traditional Chinese" msgstr "" -#: ../gtk/propertybox.c:1076 +#: ../gtk/propertybox.c:1078 msgid "Norwegian" msgstr "" -#: ../gtk/propertybox.c:1077 +#: ../gtk/propertybox.c:1079 msgid "Hebrew" msgstr "" -#: ../gtk/propertybox.c:1078 +#: ../gtk/propertybox.c:1080 msgid "Serbian" msgstr "" -#: ../gtk/propertybox.c:1145 +#: ../gtk/propertybox.c:1147 msgid "" "You need to restart linphone for the new language selection to take effect." msgstr "您需要重新啟動 linphone 才能讓新選擇的語言生效。" -#: ../gtk/propertybox.c:1223 +#: ../gtk/propertybox.c:1225 msgid "None" msgstr "" -#: ../gtk/propertybox.c:1227 +#: ../gtk/propertybox.c:1229 msgid "SRTP" msgstr "" -#: ../gtk/propertybox.c:1233 +#: ../gtk/propertybox.c:1235 msgid "ZRTP" msgstr "" @@ -467,110 +467,114 @@ msgstr "" msgid "Enter your linphone.org username" msgstr "" -#: ../gtk/setupwizard.c:96 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 +#: ../gtk/setupwizard.c:102 ../gtk/parameters.ui.h:79 ../gtk/ldap.ui.h:4 msgid "Username:" msgstr "使用者名稱:" -#: ../gtk/setupwizard.c:98 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 +#: ../gtk/setupwizard.c:104 ../gtk/password.ui.h:4 ../gtk/ldap.ui.h:5 msgid "Password:" msgstr "密碼: " -#: ../gtk/setupwizard.c:118 +#: ../gtk/setupwizard.c:124 msgid "Enter your account informations" msgstr "" -#: ../gtk/setupwizard.c:125 +#: ../gtk/setupwizard.c:140 #, fuzzy msgid "Username*" msgstr "使用者名稱" -#: ../gtk/setupwizard.c:126 +#: ../gtk/setupwizard.c:141 #, fuzzy msgid "Password*" msgstr "密碼" -#: ../gtk/setupwizard.c:129 +#: ../gtk/setupwizard.c:144 msgid "Domain*" msgstr "" -#: ../gtk/setupwizard.c:130 +#: ../gtk/setupwizard.c:145 msgid "Proxy" msgstr "" -#: ../gtk/setupwizard.c:302 +#: ../gtk/setupwizard.c:317 msgid "(*) Required fields" msgstr "" -#: ../gtk/setupwizard.c:303 +#: ../gtk/setupwizard.c:318 #, fuzzy msgid "Username: (*)" msgstr "使用者名稱:" -#: ../gtk/setupwizard.c:305 +#: ../gtk/setupwizard.c:320 #, fuzzy msgid "Password: (*)" msgstr "密碼: " -#: ../gtk/setupwizard.c:307 +#: ../gtk/setupwizard.c:322 msgid "Email: (*)" msgstr "" -#: ../gtk/setupwizard.c:309 +#: ../gtk/setupwizard.c:324 msgid "Confirm your password: (*)" msgstr "" -#: ../gtk/setupwizard.c:373 +#: ../gtk/setupwizard.c:338 +msgid "Keep me informed with linphone updates" +msgstr "" + +#: ../gtk/setupwizard.c:394 msgid "" "Error, account not validated, username already used or server unreachable.\n" "Please go back and try again." msgstr "" -#: ../gtk/setupwizard.c:384 +#: ../gtk/setupwizard.c:405 msgid "Thank you. Your account is now configured and ready for use." msgstr "謝謝您。您的帳號已設定完成並且可以使用。" -#: ../gtk/setupwizard.c:392 +#: ../gtk/setupwizard.c:413 msgid "" "Please validate your account by clicking on the link we just sent you by " "email.\n" "Then come back here and press Next button." msgstr "" -#: ../gtk/setupwizard.c:564 +#: ../gtk/setupwizard.c:600 #, fuzzy msgid "SIP account configuration assistant" msgstr "帳號設定助理" -#: ../gtk/setupwizard.c:582 +#: ../gtk/setupwizard.c:618 msgid "Welcome to the account setup assistant" msgstr "歡迎使用帳號設定助理" -#: ../gtk/setupwizard.c:587 +#: ../gtk/setupwizard.c:623 msgid "Account setup assistant" msgstr "帳號設定助理" -#: ../gtk/setupwizard.c:593 +#: ../gtk/setupwizard.c:629 #, fuzzy msgid "Configure your account (step 1/1)" msgstr "設定 SIP 帳號" -#: ../gtk/setupwizard.c:598 +#: ../gtk/setupwizard.c:634 msgid "Enter your sip username (step 1/1)" msgstr "" -#: ../gtk/setupwizard.c:602 +#: ../gtk/setupwizard.c:638 msgid "Enter account information (step 1/2)" msgstr "" -#: ../gtk/setupwizard.c:611 +#: ../gtk/setupwizard.c:647 msgid "Validation (step 2/2)" msgstr "" -#: ../gtk/setupwizard.c:616 +#: ../gtk/setupwizard.c:652 msgid "Error" msgstr "" -#: ../gtk/setupwizard.c:620 ../gtk/audio_assistant.c:519 +#: ../gtk/setupwizard.c:656 ../gtk/audio_assistant.c:527 msgid "Terminating" msgstr "" @@ -641,131 +645,131 @@ msgstr "ICE 過濾器" msgid "Direct or through server" msgstr "" -#: ../gtk/incall_view.c:266 ../gtk/incall_view.c:276 +#: ../gtk/incall_view.c:267 ../gtk/incall_view.c:279 #, c-format msgid "" "download: %f\n" "upload: %f (kbit/s)" msgstr "" -#: ../gtk/incall_view.c:271 ../gtk/incall_view.c:272 +#: ../gtk/incall_view.c:272 ../gtk/incall_view.c:274 #, c-format -msgid "%ix%i" +msgid "%ix%i @ %f fps" msgstr "" -#: ../gtk/incall_view.c:301 +#: ../gtk/incall_view.c:304 #, c-format msgid "%.3f seconds" msgstr "" -#: ../gtk/incall_view.c:399 ../gtk/main.ui.h:12 +#: ../gtk/incall_view.c:407 ../gtk/main.ui.h:12 msgid "Hang up" msgstr "" -#: ../gtk/incall_view.c:492 +#: ../gtk/incall_view.c:501 msgid "Calling..." msgstr "播打..." -#: ../gtk/incall_view.c:495 ../gtk/incall_view.c:698 +#: ../gtk/incall_view.c:504 ../gtk/incall_view.c:707 msgid "00::00::00" msgstr "00::00::00" -#: ../gtk/incall_view.c:506 +#: ../gtk/incall_view.c:515 msgid "Incoming call" msgstr "來電" -#: ../gtk/incall_view.c:543 +#: ../gtk/incall_view.c:552 msgid "good" msgstr "" -#: ../gtk/incall_view.c:545 +#: ../gtk/incall_view.c:554 msgid "average" msgstr "" -#: ../gtk/incall_view.c:547 +#: ../gtk/incall_view.c:556 msgid "poor" msgstr "" -#: ../gtk/incall_view.c:549 +#: ../gtk/incall_view.c:558 msgid "very poor" msgstr "" -#: ../gtk/incall_view.c:551 +#: ../gtk/incall_view.c:560 msgid "too bad" msgstr "" -#: ../gtk/incall_view.c:552 ../gtk/incall_view.c:568 +#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:577 msgid "unavailable" msgstr "" -#: ../gtk/incall_view.c:660 +#: ../gtk/incall_view.c:669 msgid "Secured by SRTP" msgstr "" -#: ../gtk/incall_view.c:666 +#: ../gtk/incall_view.c:675 #, c-format msgid "Secured by ZRTP - [auth token: %s]" msgstr "" -#: ../gtk/incall_view.c:672 +#: ../gtk/incall_view.c:681 msgid "Set unverified" msgstr "" -#: ../gtk/incall_view.c:672 ../gtk/main.ui.h:4 +#: ../gtk/incall_view.c:681 ../gtk/main.ui.h:4 msgid "Set verified" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In conference" msgstr "" -#: ../gtk/incall_view.c:693 +#: ../gtk/incall_view.c:702 msgid "In call" msgstr "通話中" -#: ../gtk/incall_view.c:729 +#: ../gtk/incall_view.c:738 msgid "Paused call" msgstr "暫停通話" -#: ../gtk/incall_view.c:742 +#: ../gtk/incall_view.c:751 #, c-format msgid "%02i::%02i::%02i" msgstr "%02i::%02i::%02i" -#: ../gtk/incall_view.c:760 +#: ../gtk/incall_view.c:772 msgid "Call ended." msgstr "通話結束。" -#: ../gtk/incall_view.c:791 +#: ../gtk/incall_view.c:803 msgid "Transfer in progress" msgstr "" -#: ../gtk/incall_view.c:794 +#: ../gtk/incall_view.c:806 #, fuzzy msgid "Transfer done." msgstr "轉接" -#: ../gtk/incall_view.c:797 +#: ../gtk/incall_view.c:809 #, fuzzy msgid "Transfer failed." msgstr "轉接" -#: ../gtk/incall_view.c:841 +#: ../gtk/incall_view.c:853 msgid "Resume" msgstr "繼續" -#: ../gtk/incall_view.c:848 ../gtk/main.ui.h:9 +#: ../gtk/incall_view.c:860 ../gtk/main.ui.h:9 msgid "Pause" msgstr "暫停" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, c-format msgid "" "Recording into\n" "%s %s" msgstr "" -#: ../gtk/incall_view.c:913 +#: ../gtk/incall_view.c:926 #, fuzzy msgid "(Paused)" msgstr "暫停" @@ -801,7 +805,7 @@ msgstr "" msgid "Too loud" msgstr "" -#: ../gtk/audio_assistant.c:316 +#: ../gtk/audio_assistant.c:318 #, fuzzy msgid "" "Welcome !\n" @@ -810,59 +814,59 @@ msgstr "" "歡迎!\n" "這個助理會協助您使用電話的 SIP 帳號。" -#: ../gtk/audio_assistant.c:326 +#: ../gtk/audio_assistant.c:328 #, fuzzy msgid "Capture device" msgstr "捕捉裝置:" -#: ../gtk/audio_assistant.c:327 +#: ../gtk/audio_assistant.c:329 msgid "Recorded volume" msgstr "" -#: ../gtk/audio_assistant.c:331 +#: ../gtk/audio_assistant.c:333 msgid "No voice" msgstr "" -#: ../gtk/audio_assistant.c:367 +#: ../gtk/audio_assistant.c:369 #, fuzzy msgid "Playback device" msgstr "播放裝置" -#: ../gtk/audio_assistant.c:368 +#: ../gtk/audio_assistant.c:370 msgid "Play three beeps" msgstr "" -#: ../gtk/audio_assistant.c:400 +#: ../gtk/audio_assistant.c:403 msgid "Press the record button and say some words" msgstr "" -#: ../gtk/audio_assistant.c:401 +#: ../gtk/audio_assistant.c:404 msgid "Listen to your record voice" msgstr "" -#: ../gtk/audio_assistant.c:430 +#: ../gtk/audio_assistant.c:433 msgid "Let's start Linphone now" msgstr "" -#: ../gtk/audio_assistant.c:488 +#: ../gtk/audio_assistant.c:496 #, fuzzy msgid "Audio Assistant" msgstr "帳號設定助理" -#: ../gtk/audio_assistant.c:498 ../gtk/main.ui.h:31 +#: ../gtk/audio_assistant.c:506 ../gtk/main.ui.h:31 #, fuzzy msgid "Audio assistant" msgstr "帳號設定助理" -#: ../gtk/audio_assistant.c:503 +#: ../gtk/audio_assistant.c:511 msgid "Mic Gain calibration" msgstr "" -#: ../gtk/audio_assistant.c:509 +#: ../gtk/audio_assistant.c:517 msgid "Speaker volume calibration" msgstr "" -#: ../gtk/audio_assistant.c:514 +#: ../gtk/audio_assistant.c:522 msgid "Record and Play" msgstr "" @@ -1815,96 +1819,65 @@ msgstr "連線中..." msgid "Please wait while fetching configuration from server..." msgstr "" -#: ../coreapi/linphonecore.c:242 -msgid "aborted" -msgstr "已放棄" - -#: ../coreapi/linphonecore.c:245 -msgid "completed" -msgstr "已完成" - -#: ../coreapi/linphonecore.c:248 -msgid "missed" -msgstr "未接" - -#: ../coreapi/linphonecore.c:253 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" -"%s 於 %s\n" -"從:%s\n" -"到:%s\n" -"狀態:%s\n" -"持續時間:%i 分 %i 秒\n" - -#: ../coreapi/linphonecore.c:254 -msgid "Outgoing call" -msgstr "去電" - -#: ../coreapi/linphonecore.c:1287 +#: ../coreapi/linphonecore.c:1034 msgid "Ready" msgstr "準備就緒" -#: ../coreapi/linphonecore.c:2248 +#: ../coreapi/linphonecore.c:1967 #, fuzzy msgid "Configuring" msgstr "確認" -#: ../coreapi/linphonecore.c:2410 +#: ../coreapi/linphonecore.c:2133 msgid "Looking for telephone number destination..." msgstr "尋找電話號碼目的端..." -#: ../coreapi/linphonecore.c:2413 +#: ../coreapi/linphonecore.c:2136 msgid "Could not resolve this number." msgstr "無法解析這個號碼。" #. must be known at that time -#: ../coreapi/linphonecore.c:2695 +#: ../coreapi/linphonecore.c:2418 msgid "Contacting" msgstr "正在連絡" -#: ../coreapi/linphonecore.c:2702 +#: ../coreapi/linphonecore.c:2425 msgid "Could not call" msgstr "無法通話" -#: ../coreapi/linphonecore.c:2852 +#: ../coreapi/linphonecore.c:2576 msgid "Sorry, we have reached the maximum number of simultaneous calls" msgstr "抱歉,我們已達瀏同步通話的最大數目" -#: ../coreapi/linphonecore.c:3022 +#: ../coreapi/linphonecore.c:2745 msgid "is contacting you" msgstr "正在連絡您" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid " and asked autoanswer." msgstr "並要求自動接聽。" -#: ../coreapi/linphonecore.c:3023 +#: ../coreapi/linphonecore.c:2746 msgid "." msgstr "." -#: ../coreapi/linphonecore.c:3139 +#: ../coreapi/linphonecore.c:2865 msgid "Modifying call parameters..." msgstr "修改通話參數..." -#: ../coreapi/linphonecore.c:3469 +#: ../coreapi/linphonecore.c:3194 msgid "Connected." msgstr "已連線。" -#: ../coreapi/linphonecore.c:3495 +#: ../coreapi/linphonecore.c:3220 msgid "Call aborted" msgstr "通話已放棄" -#: ../coreapi/linphonecore.c:3685 +#: ../coreapi/linphonecore.c:3412 msgid "Could not pause the call" msgstr "無法暫停通話" -#: ../coreapi/linphonecore.c:3690 +#: ../coreapi/linphonecore.c:3417 msgid "Pausing the current call..." msgstr "暫停目前的通話..." @@ -1969,14 +1942,14 @@ msgstr "時間長度" msgid "Unknown-bug" msgstr "不明錯誤" -#: ../coreapi/proxy.c:279 +#: ../coreapi/proxy.c:314 msgid "" "The sip proxy address you entered is invalid, it must start with \"sip:\" " "followed by a hostname." msgstr "" "您輸入的 sip 代理位址是無效的,它必須要以「sip:」開頭,後面接主機名稱。" -#: ../coreapi/proxy.c:285 +#: ../coreapi/proxy.c:320 msgid "" "The sip identity you entered is invalid.\n" "It should look like sip:username@proxydomain, such as sip:alice@example.net" @@ -1984,130 +1957,155 @@ msgstr "" "您輸入的 sip 身分是無效的。\n" "它應該看起來像 sip:使用者名稱@代理網域,像是 sip:alice@example.net" -#: ../coreapi/proxy.c:1299 +#: ../coreapi/proxy.c:1369 #, c-format msgid "Could not login as %s" msgstr "無法以 %s 登入" -#: ../coreapi/callbacks.c:354 +#: ../coreapi/callbacks.c:355 msgid "Remote ringing." msgstr "遠端響鈴。" -#: ../coreapi/callbacks.c:370 +#: ../coreapi/callbacks.c:373 msgid "Remote ringing..." msgstr "遠端響鈴..." -#: ../coreapi/callbacks.c:381 +#: ../coreapi/callbacks.c:384 msgid "Early media." msgstr "早期媒體。" -#: ../coreapi/callbacks.c:432 +#: ../coreapi/callbacks.c:435 #, c-format msgid "Call with %s is paused." msgstr "和 %s 的通話已暫停。" -#: ../coreapi/callbacks.c:445 +#: ../coreapi/callbacks.c:448 #, c-format msgid "Call answered by %s - on hold." msgstr "通話由 %s 接聽 - 保留中。" -#: ../coreapi/callbacks.c:456 +#: ../coreapi/callbacks.c:459 msgid "Call resumed." msgstr "通話已繼續。" -#: ../coreapi/callbacks.c:461 +#: ../coreapi/callbacks.c:464 #, c-format msgid "Call answered by %s." msgstr "通話由 %s 接聽。" -#: ../coreapi/callbacks.c:480 +#: ../coreapi/callbacks.c:483 msgid "Incompatible, check codecs or security settings..." msgstr "" -#: ../coreapi/callbacks.c:531 +#: ../coreapi/callbacks.c:512 #, fuzzy msgid "We have been resumed." msgstr "我們要繼續了..." -#: ../coreapi/callbacks.c:541 +#: ../coreapi/callbacks.c:521 msgid "We are paused by other party." msgstr "" -#: ../coreapi/callbacks.c:558 +#: ../coreapi/callbacks.c:556 msgid "Call is updated by remote." msgstr "" -#: ../coreapi/callbacks.c:637 +#: ../coreapi/callbacks.c:658 msgid "Call terminated." msgstr "通話已終止。" -#: ../coreapi/callbacks.c:666 +#: ../coreapi/callbacks.c:687 msgid "User is busy." msgstr "使用者現正忙碌。" -#: ../coreapi/callbacks.c:667 +#: ../coreapi/callbacks.c:688 msgid "User is temporarily unavailable." msgstr "使用者暫時無法聯繫。" #. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:669 +#: ../coreapi/callbacks.c:690 msgid "User does not want to be disturbed." msgstr "使用者不想要被打擾。" -#: ../coreapi/callbacks.c:670 +#: ../coreapi/callbacks.c:691 msgid "Call declined." msgstr "通話被拒接。" -#: ../coreapi/callbacks.c:685 +#: ../coreapi/callbacks.c:706 msgid "Request timeout." msgstr "" -#: ../coreapi/callbacks.c:716 +#: ../coreapi/callbacks.c:737 msgid "Redirected" msgstr "已重新導向" -#: ../coreapi/callbacks.c:766 +#: ../coreapi/callbacks.c:787 msgid "Incompatible media parameters." msgstr "" -#: ../coreapi/callbacks.c:777 +#: ../coreapi/callbacks.c:798 msgid "Call failed." msgstr "通話失敗。" -#: ../coreapi/callbacks.c:852 +#: ../coreapi/callbacks.c:878 #, c-format msgid "Registration on %s successful." msgstr "在 %s 註冊成功。" -#: ../coreapi/callbacks.c:853 +#: ../coreapi/callbacks.c:879 #, c-format msgid "Unregistration on %s done." msgstr "在 %s 取消註冊完成。" -#: ../coreapi/callbacks.c:875 +#: ../coreapi/callbacks.c:897 msgid "no response timeout" msgstr "沒有回應逾時" -#: ../coreapi/callbacks.c:878 +#: ../coreapi/callbacks.c:900 #, c-format msgid "Registration on %s failed: %s" msgstr "在 %s 註冊失敗:%s" -#: ../coreapi/callbacks.c:885 +#: ../coreapi/callbacks.c:907 msgid "Service unavailable, retrying" msgstr "" -#: ../coreapi/linphonecall.c:175 +#: ../coreapi/linphonecall.c:177 #, fuzzy, c-format msgid "Authentication token is %s" msgstr "驗證失敗" -#: ../coreapi/linphonecall.c:2994 +#: ../coreapi/linphonecall.c:2932 #, c-format msgid "You have missed %i call." msgid_plural "You have missed %i calls." msgstr[0] "您有 %i 通未接來電。" +#~ msgid "aborted" +#~ msgstr "已放棄" + +#~ msgid "completed" +#~ msgstr "已完成" + +#~ msgid "missed" +#~ msgstr "未接" + +#~ msgid "" +#~ "%s at %s\n" +#~ "From: %s\n" +#~ "To: %s\n" +#~ "Status: %s\n" +#~ "Duration: %i mn %i sec\n" +#~ msgstr "" +#~ "%s 於 %s\n" +#~ "從:%s\n" +#~ "到:%s\n" +#~ "狀態:%s\n" +#~ "持續時間:%i 分 %i 秒\n" + +#~ msgid "Outgoing call" +#~ msgstr "去電" + #~ msgid "No response." #~ msgstr "沒有回應。" diff --git a/share/CMakeLists.txt b/share/CMakeLists.txt index 8d15a6f5c..03b36a74d 100644 --- a/share/CMakeLists.txt +++ b/share/CMakeLists.txt @@ -1,17 +1,32 @@ +############################################################################ +# CMakeLists.txt +# Copyright (C) 2014 Belledonne Communications, Grenoble France +# +############################################################################ +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################ + install(FILES archived-rootca.pem RENAME rootca.pem - COMPONENT COMP_liblinphone DESTINATION share/linphone PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ) install(FILES ringback.wav - COMPONENT COMP_liblinphone DESTINATION share/sounds/linphone PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ) add_subdirectory(rings) - -install(FILES ../mediastreamer2/src/voip/nowebcamCIF.jpg - COMPONENT COMP_liblinphone - DESTINATION share/images - PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ) diff --git a/share/audio-assistant.desktop.in b/share/audio-assistant.desktop.in index 5e164ca2b..8f2ef4c54 100644 --- a/share/audio-assistant.desktop.in +++ b/share/audio-assistant.desktop.in @@ -1,7 +1,9 @@ [Desktop Entry] Name=Audio assistant +Name[ru]=Помощник аудио Comment=Linphone audio assistant Comment[fr]=Assistant audio de Linphone. +Comment[ru]=Помощник аудио Linphone Type=Application Exec=linphone --run-audio-assistant Icon=/usr/local/share/pixmaps/linphone/linphone.png diff --git a/share/linphone.desktop.in b/share/linphone.desktop.in index d8ab62a5b..c162ed904 100644 --- a/share/linphone.desktop.in +++ b/share/linphone.desktop.in @@ -3,6 +3,43 @@ Name=Linphone Comment=Linphone is a web-phone Comment[fr]=Linphone est un web-phone. Comment[de]=Linphone ist ein web-phone. +Comment[af]=Linphone is 'n webtelefoon +Comment[sq]=Linphone është një telefon interneti +Comment[ast]=Linphone ye un teléfonu web +Comment[bn]=Linphone একটি ওয়েব ফোন +Comment[bs]=Linphone je mrežni telefon +Comment[pt_BR]=Linphone é um telefone web +Comment[bg]=Linphone е уеб телефон +Comment[ca@valencia]=El Linphone és un telèfon web +Comment[ca]=El Linphone és un telèfon web +Comment[zh_HK]=Linphone 是網絡電話(web-phone) +Comment[zh_TW]=Linphone 是網路電話(web-phone) +Comment[zh_CN]=Linphone 是一个网络电话程序 +Comment[crh]=Linphone bir web-telefonudur +Comment[nl]=Linphone is een webtelefoon +Comment[da]=Linphone er en nettelefon +Comment[cs]=Linphone webový telefon +Comment[fi]=Linphone on verkkopuhelin +Comment[gl]=Linphone é un teléfono-web +Comment[el]=Το Linphone είναι ένα διαδικτυακό τηλέφωνο +Comment[hu]=A Linphone egy webes telefon +Comment[is]=Linphone er vefsími +Comment[it]=Linphone è un telefono web +Comment[ja]=Linphone はウェブ電話です +Comment[ky]=Linphone - бул веб - телефон +Comment[ms]=Linphone adalah telefon-sesawang +Comment[oc]=Linphone es una aisina de telefonia IP +Comment[pl]=Rozbudowany telefon internetowy z funkcją wideorozmowy +Comment[nb]=Lintelefon er en nett-telefon +Comment[pt]=Linphone é um telefone da internet +Comment[ro]=Linphone este un telefon web +Comment[ru]=Linphone — это веб-телефон +Comment[sl]=Linphone je spletni telefon +Comment[sv]=Webbtelefon +Comment[es]=Linphone es un teléfono web +Comment[vi]=Linphone là một điện thoại web +Comment[uk]=Інтернет-телефон +Comment[tr]=Linphone bir web-telefonudur Type=Application Exec=linphone Icon=@prefix@/share/pixmaps/linphone/linphone.png diff --git a/share/rings/CMakeLists.txt b/share/rings/CMakeLists.txt index cf359bb4e..63f2c47ac 100644 --- a/share/rings/CMakeLists.txt +++ b/share/rings/CMakeLists.txt @@ -1,3 +1,25 @@ +############################################################################ +# CMakeLists.txt +# Copyright (C) 2014 Belledonne Communications, Grenoble France +# +############################################################################ +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +############################################################################ + install(FILES oldphone.wav toy-mono.wav COMPONENT COMP_liblinphone DESTINATION share/sounds/linphone/rings diff --git a/tester/Makefile.am b/tester/Makefile.am index 348306bca..6e52d21b5 100644 --- a/tester/Makefile.am +++ b/tester/Makefile.am @@ -21,13 +21,14 @@ liblinphonetester_la_SOURCES = tester.c \ flexisip_tester.c \ stun_tester.c \ remote_provisioning_tester.c \ - quality_reporting_tester.c + quality_reporting_tester.c \ + transport_tester.c liblinphonetester_la_LDFLAGS= -no-undefined liblinphonetester_la_LIBADD= ../coreapi/liblinphone.la $(CUNIT_LIBS) AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/coreapi -AM_CFLAGS = $(STRICT_OPTIONS) -DIN_LINPHONE $(ORTP_CFLAGS) $(MEDIASTREAMER_CFLAGS) $(CUNIT_CFLAGS) $(BELLESIP_CFLAGS) $(LIBXML2_CFLAGS) $(SQLITE3_CFLAGS) +AM_CFLAGS = $(STRICT_OPTIONS) $(STRICT_OPTIONS_CC) -DIN_LINPHONE $(ORTP_CFLAGS) $(MEDIASTREAMER_CFLAGS) $(CUNIT_CFLAGS) $(BELLESIP_CFLAGS) $(LIBXML2_CFLAGS) $(SQLITE3_CFLAGS) if !BUILD_IOS diff --git a/tester/README b/tester/README new file mode 100644 index 000000000..dfc060ecc --- /dev/null +++ b/tester/README @@ -0,0 +1,9 @@ +This is the test suite of liblinphone, with many tests suites for Register, Calls, Message, Presence. + +All thoses tests suites require a SIP server configured accordingly in order to execute. Naturally a Flexisip SIP server is used, whose configuration is put in the flexisip/ directory here. + +In order to invoke it, just place into the tester directory and run +$ flexisip --configfile flexisip/flexisip.conf + +The tester_hosts file contains the host-like DNS configuration file to be used by the test suite in order to resolve the virtual SIP domains used by the SIP stack. +It is possible to run the flexisip SIP server and the test suite on the same machine by passing a new tester_hosts file where domains resolve to 127.0.0.1 to the tester, using the --dns-hosts option. diff --git a/tester/call_tester.c b/tester/call_tester.c index b507b5855..35b4c2bdd 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -18,14 +18,24 @@ #include +#include +#include #include "CUnit/Basic.h" #include "linphonecore.h" #include "lpconfig.h" #include "private.h" #include "liblinphone_tester.h" +static void srtp_call(void); static void call_base(LinphoneMediaEncryption mode, bool_t enable_video,bool_t enable_relay,LinphoneFirewallPolicy policy); -static void disable_all_codecs_except_one(LinphoneCore *lc, const char *mime); +static void disable_all_audio_codecs_except_one(LinphoneCore *lc, const char *mime, int rate); + +// prototype definition for call_recording() +#ifdef ANDROID +#ifdef HAVE_OPENH264 +extern void libmsopenh264_init(void); +#endif +#endif void call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *msg){ char* to=linphone_address_as_string(linphone_call_get_call_log(call)->to); @@ -115,8 +125,8 @@ static void linphone_call_cb(LinphoneCall *call,void * user_data) { void liblinphone_tester_check_rtcp(LinphoneCoreManager* caller, LinphoneCoreManager* callee) { LinphoneCall *c1,*c2; - int i; int dummy=0; + MSTimeSpec ts; c1=linphone_core_get_current_call(caller->lc); c2=linphone_core_get_current_call(callee->lc); @@ -127,7 +137,9 @@ void liblinphone_tester_check_rtcp(LinphoneCoreManager* caller, LinphoneCoreMana if (!c1 || !c2) return; linphone_call_ref(c1); linphone_call_ref(c2); - for (i=0; i<24 /*=12s need at least one exchange of SR to maybe 10s*/; i++) { + + liblinphone_tester_clock_start(&ts); + do { if (linphone_call_get_audio_stats(c1)->round_trip_delay >0.0 && linphone_call_get_audio_stats(c2)->round_trip_delay >0.0 && (!linphone_call_log_video_enabled(linphone_call_get_call_log(c1)) || linphone_call_get_video_stats(c1)->round_trip_delay>0.0) @@ -136,8 +148,7 @@ void liblinphone_tester_check_rtcp(LinphoneCoreManager* caller, LinphoneCoreMana } wait_for_until(caller->lc,callee->lc,&dummy,1,500); /*just to sleep while iterating*/ - - } + }while (!liblinphone_tester_clock_elapsed(&ts,12000)); CU_ASSERT_TRUE(linphone_call_get_audio_stats(c1)->round_trip_delay>0.0); CU_ASSERT_TRUE(linphone_call_get_audio_stats(c2)->round_trip_delay>0.0); if (linphone_call_log_video_enabled(linphone_call_get_call_log(c1))) { @@ -150,10 +161,10 @@ void liblinphone_tester_check_rtcp(LinphoneCoreManager* caller, LinphoneCoreMana linphone_call_unref(c2); } -bool_t call_with_params(LinphoneCoreManager* caller_mgr +bool_t call_with_params2(LinphoneCoreManager* caller_mgr ,LinphoneCoreManager* callee_mgr , const LinphoneCallParams *caller_params - , const LinphoneCallParams *callee_params) { + , const LinphoneCallParams *callee_params, bool_t build_callee_params) { int retry=0; stats initial_caller=caller_mgr->stat; stats initial_callee=callee_mgr->stat; @@ -205,10 +216,16 @@ bool_t call_with_params(LinphoneCoreManager* caller_mgr } linphone_address_destroy(callee_from); } - if (callee_params) + if (callee_params){ linphone_core_accept_call_with_params(callee_mgr->lc,linphone_core_get_current_call(callee_mgr->lc),callee_params); - else + }else if (build_callee_params){ + LinphoneCallParams *default_params=linphone_core_create_call_params(callee_mgr->lc,linphone_core_get_current_call(callee_mgr->lc)); + ms_error("Created default call params with video=%i", linphone_call_params_video_enabled(default_params)); + linphone_core_accept_call_with_params(callee_mgr->lc,linphone_core_get_current_call(callee_mgr->lc),default_params); + linphone_call_params_destroy(default_params); + }else{ linphone_core_accept_call(callee_mgr->lc,linphone_core_get_current_call(callee_mgr->lc)); + } CU_ASSERT_TRUE(wait_for(callee_mgr->lc,caller_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallConnected,initial_callee.number_of_LinphoneCallConnected+1)); CU_ASSERT_TRUE(wait_for(callee_mgr->lc,caller_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallConnected,initial_callee.number_of_LinphoneCallConnected+1)); @@ -228,11 +245,19 @@ bool_t call_with_params(LinphoneCoreManager* caller_mgr const LinphoneCallParams* call_param = linphone_call_get_current_params(linphone_core_get_current_call(callee_mgr->lc)); CU_ASSERT_EQUAL(linphone_call_params_get_media_encryption(call_param),linphone_core_get_media_encryption(caller_mgr->lc)); call_param = linphone_call_get_current_params(linphone_core_get_current_call(caller_mgr->lc)); - CU_ASSERT_EQUAL(linphone_call_params_get_media_encryption(call_param),linphone_core_get_media_encryption(caller_mgr->lc)); + CU_ASSERT_EQUAL(linphone_call_params_get_media_encryption(call_param),linphone_core_get_media_encryption(callee_mgr->lc)); } } return result; } + +bool_t call_with_params(LinphoneCoreManager* caller_mgr + ,LinphoneCoreManager* callee_mgr + , const LinphoneCallParams *caller_params + , const LinphoneCallParams *callee_params){ + return call_with_params2(caller_mgr,callee_mgr,caller_params,callee_params,FALSE); +} + bool_t call_with_caller_params(LinphoneCoreManager* caller_mgr,LinphoneCoreManager* callee_mgr, const LinphoneCallParams *params) { return call_with_params(caller_mgr,callee_mgr,params,NULL); } @@ -241,10 +266,12 @@ bool_t call(LinphoneCoreManager* caller_mgr,LinphoneCoreManager* callee_mgr){ return call_with_params(caller_mgr,callee_mgr,NULL,NULL); } -static void end_call(LinphoneCoreManager *m1, LinphoneCoreManager *m2){ +void end_call(LinphoneCoreManager *m1, LinphoneCoreManager *m2){ linphone_core_terminate_all_calls(m1->lc); CU_ASSERT_TRUE(wait_for(m1->lc,m2->lc,&m1->stat.number_of_LinphoneCallEnd,1)); CU_ASSERT_TRUE(wait_for(m1->lc,m2->lc,&m2->stat.number_of_LinphoneCallEnd,1)); + CU_ASSERT_TRUE(wait_for(m1->lc,m2->lc,&m1->stat.number_of_LinphoneCallReleased,1)); + CU_ASSERT_TRUE(wait_for(m1->lc,m2->lc,&m2->stat.number_of_LinphoneCallReleased,1)); } static void simple_call(void) { @@ -420,28 +447,47 @@ static void call_with_specified_codec_bitrate(void) { LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); const LinphoneCallStats *pauline_stats,*marie_stats; bool_t call_ok; - if (linphone_core_find_payload_type(marie->lc,"opus",48000,-1)==NULL){ + char * codec = "opus"; + int rate = 48000; + int min_bw=24; + int max_bw=40; + +#ifdef __arm__ + if (ms_get_cpu_count() <2) { /*2 opus codec channel + resampler is too much for a single core*/ +#ifndef ANDROID + codec = "speex"; + rate = 8000; + min_bw=20; + max_bw=35; +#else + CU_PASS("Test requires at least a dual core"); + goto end; +#endif + } +#endif + + if (linphone_core_find_payload_type(marie->lc,codec,rate,-1)==NULL){ ms_warning("opus codec not supported, test skipped."); goto end; } - disable_all_codecs_except_one(marie->lc,"opus"); - disable_all_codecs_except_one(pauline->lc,"opus"); + disable_all_audio_codecs_except_one(marie->lc,codec,rate); + disable_all_audio_codecs_except_one(pauline->lc,codec,rate); linphone_core_set_payload_type_bitrate(marie->lc, - linphone_core_find_payload_type(marie->lc,"opus",48000,-1), - 50); + linphone_core_find_payload_type(marie->lc,codec,rate,-1), + max_bw); linphone_core_set_payload_type_bitrate(pauline->lc, - linphone_core_find_payload_type(pauline->lc,"opus",48000,-1), - 24); + linphone_core_find_payload_type(pauline->lc,codec,rate,-1), + min_bw); CU_ASSERT_TRUE((call_ok=call(pauline,marie))); if (!call_ok) goto end; liblinphone_tester_check_rtcp(marie,pauline); marie_stats=linphone_call_get_audio_stats(linphone_core_get_current_call(marie->lc)); pauline_stats=linphone_call_get_audio_stats(linphone_core_get_current_call(pauline->lc)); - CU_ASSERT_TRUE(marie_stats->download_bandwidth<30); - CU_ASSERT_TRUE(pauline_stats->download_bandwidth>45); + CU_ASSERT_TRUE(marie_stats->download_bandwidth<(min_bw+5+min_bw*.1)); + CU_ASSERT_TRUE(pauline_stats->download_bandwidth>(max_bw-5-max_bw*.1)); end: linphone_core_manager_destroy(marie); @@ -535,7 +581,7 @@ static void cancelled_call(void) { linphone_core_manager_destroy(pauline); } -static void disable_all_codecs_except_one(LinphoneCore *lc, const char *mime){ +static void disable_all_audio_codecs_except_one(LinphoneCore *lc, const char *mime, int rate){ const MSList *elem=linphone_core_get_audio_codecs(lc); PayloadType *pt; @@ -543,24 +589,38 @@ static void disable_all_codecs_except_one(LinphoneCore *lc, const char *mime){ pt=(PayloadType*)elem->data; linphone_core_enable_payload_type(lc,pt,FALSE); } - pt=linphone_core_find_payload_type(lc,mime,-1,-1); + pt=linphone_core_find_payload_type(lc,mime,rate,-1); CU_ASSERT_PTR_NOT_NULL_FATAL(pt); linphone_core_enable_payload_type(lc,pt,TRUE); } +#ifdef VIDEO_ENABLED +static void disable_all_video_codecs_except_one(LinphoneCore *lc, const char *mime) { + const MSList *codecs = linphone_core_get_video_codecs(lc); + const MSList *it = NULL; + PayloadType *pt = NULL; + + for(it = codecs; it != NULL; it = it->next) { + linphone_core_enable_payload_type(lc, (PayloadType *)it->data, FALSE); + } + CU_ASSERT_PTR_NOT_NULL_FATAL(pt = linphone_core_find_payload_type(lc, mime, -1, -1)); + linphone_core_enable_payload_type(lc, pt, TRUE); +} +#endif + static void call_failed_because_of_codecs(void) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); LinphoneCall* out_call; - disable_all_codecs_except_one(marie->lc,"pcmu"); - disable_all_codecs_except_one(pauline->lc,"pcma"); + disable_all_audio_codecs_except_one(marie->lc,"pcmu",-1); + disable_all_audio_codecs_except_one(pauline->lc,"pcma",-1); out_call = linphone_core_invite(pauline->lc,"marie"); linphone_call_ref(out_call); CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallOutgoingInit,1)); - /*flexisip will retain the 488 until the "urgent reply" timeout arrives.*/ - CU_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallError,1,6000)); + /*flexisip will retain the 488 until the "urgent reply" timeout (I.E 5s) arrives.*/ + CU_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallError,1,7000)); CU_ASSERT_EQUAL(linphone_call_get_reason(out_call),LinphoneReasonNotAcceptable); CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallIncomingReceived,0); @@ -577,7 +637,7 @@ static void call_with_dns_time_out(void) { linphone_core_set_sip_transports(marie->lc,&transport); linphone_core_iterate(marie->lc); sal_set_dns_timeout(marie->lc->sal,0); - linphone_core_invite(marie->lc,"\"t\x8et\x8e\" sip:toto@toto.com"); /*just to use non ascii values*/ + linphone_core_invite(marie->lc,"\"t\x8et\x8e\" "); /*just to use non ascii values*/ for(i=0;i<10;i++){ ms_usleep(200000); linphone_core_iterate(marie->lc); @@ -719,8 +779,8 @@ static bool_t check_ice(LinphoneCoreManager* caller, LinphoneCoreManager* callee LinphoneCall *c1,*c2; bool_t audio_success=FALSE; bool_t video_success=FALSE; - int i; bool_t video_enabled; + MSTimeSpec ts; c1=linphone_core_get_current_call(caller->lc); c2=linphone_core_get_current_call(callee->lc); @@ -733,7 +793,8 @@ static bool_t check_ice(LinphoneCoreManager* caller, LinphoneCoreManager* callee CU_ASSERT_EQUAL(linphone_call_params_video_enabled(linphone_call_get_current_params(c1)),linphone_call_params_video_enabled(linphone_call_get_current_params(c2))); video_enabled=linphone_call_params_video_enabled(linphone_call_get_current_params(c1)); - for (i=0;i<200;i++){ + liblinphone_tester_clock_start(&ts); + do{ if ((c1 != NULL) && (c2 != NULL)) { if (linphone_call_get_audio_stats(c1)->ice_state==state && linphone_call_get_audio_stats(c2)->ice_state==state ){ @@ -743,11 +804,12 @@ static bool_t check_ice(LinphoneCoreManager* caller, LinphoneCoreManager* callee linphone_core_iterate(caller->lc); linphone_core_iterate(callee->lc); } - ms_usleep(50000); - } + ms_usleep(20000); + }while(!liblinphone_tester_clock_elapsed(&ts,10000)); if (video_enabled){ - for (i=0;i<200;i++){ + liblinphone_tester_clock_start(&ts); + do{ if ((c1 != NULL) && (c2 != NULL)) { if (linphone_call_get_video_stats(c1)->ice_state==state && linphone_call_get_video_stats(c2)->ice_state==state ){ @@ -757,8 +819,8 @@ static bool_t check_ice(LinphoneCoreManager* caller, LinphoneCoreManager* callee linphone_core_iterate(caller->lc); linphone_core_iterate(callee->lc); } - ms_usleep(50000); - } + ms_usleep(20000); + }while(!liblinphone_tester_clock_elapsed(&ts,5000)); } /*make sure encryption mode are preserved*/ @@ -1119,7 +1181,42 @@ static bool_t add_video(LinphoneCoreManager* caller,LinphoneCoreManager* callee) /*send vfu*/ linphone_call_send_vfu_request(call_obj); return wait_for(caller->lc,callee->lc,&callee->stat.number_of_IframeDecoded,initial_callee_stat.number_of_IframeDecoded+1); - } else return 0; + } + return FALSE; +} + +static bool_t remove_video(LinphoneCoreManager *caller, LinphoneCoreManager *callee) { + LinphoneCallParams *callee_params; + LinphoneCall *call_obj; + stats initial_caller_stat = caller->stat; + stats initial_callee_stat = callee->stat; + + if (!linphone_core_get_current_call(callee->lc) + || (linphone_call_get_state(linphone_core_get_current_call(callee->lc)) != LinphoneCallStreamsRunning) + || !linphone_core_get_current_call(caller->lc) + || (linphone_call_get_state(linphone_core_get_current_call(caller->lc)) != LinphoneCallStreamsRunning)) { + ms_warning("bad state for removing video"); + return FALSE; + } + + if ((call_obj = linphone_core_get_current_call(callee->lc))) { + callee_params = linphone_call_params_copy(linphone_call_get_current_params(call_obj)); + + /* Remove video. */ + linphone_call_params_enable_video(callee_params, FALSE); + linphone_core_update_call(callee->lc, call_obj, callee_params); + + CU_ASSERT_TRUE(wait_for(caller->lc, callee->lc, &caller->stat.number_of_LinphoneCallUpdatedByRemote, initial_caller_stat.number_of_LinphoneCallUpdatedByRemote + 1)); + CU_ASSERT_TRUE(wait_for(caller->lc, callee->lc, &callee->stat.number_of_LinphoneCallUpdating, initial_callee_stat.number_of_LinphoneCallUpdating + 1)); + CU_ASSERT_TRUE(wait_for(caller->lc, callee->lc, &callee->stat.number_of_LinphoneCallStreamsRunning, initial_callee_stat.number_of_LinphoneCallStreamsRunning + 1)); + CU_ASSERT_TRUE(wait_for(caller->lc, callee->lc, &caller->stat.number_of_LinphoneCallStreamsRunning, initial_caller_stat.number_of_LinphoneCallStreamsRunning + 1)); + + CU_ASSERT_FALSE(linphone_call_params_video_enabled(linphone_call_get_current_params(linphone_core_get_current_call(callee->lc)))); + CU_ASSERT_FALSE(linphone_call_params_video_enabled(linphone_call_get_current_params(linphone_core_get_current_call(caller->lc)))); + + return TRUE; + } + return FALSE; } static void call_with_video_added(void) { @@ -1158,10 +1255,60 @@ static void call_with_video_added_random_ports(void) { linphone_core_manager_destroy(pauline); } +static void call_with_several_video_switches(void) { + int dummy = 0; + LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); + CU_ASSERT_TRUE(call(pauline,marie)); + + CU_ASSERT_TRUE(add_video(pauline,marie)); + wait_for_until(pauline->lc,marie->lc,&dummy,1,1000); /* Wait for VFU request exchanges to be finished. */ + CU_ASSERT_TRUE(remove_video(pauline,marie)); + CU_ASSERT_TRUE(add_video(pauline,marie)); + wait_for_until(pauline->lc,marie->lc,&dummy,1,1000); /* Wait for VFU request exchanges to be finished. */ + CU_ASSERT_TRUE(remove_video(pauline,marie)); + /*just to sleep*/ + linphone_core_terminate_all_calls(pauline->lc); + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1)); + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1)); + + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + +static void srtp_call_with_several_video_switches(void) { + int dummy = 0; + LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); + + if (linphone_core_media_encryption_supported(marie->lc, LinphoneMediaEncryptionSRTP)) { + linphone_core_set_media_encryption(marie->lc, LinphoneMediaEncryptionSRTP); + linphone_core_set_media_encryption(pauline->lc, LinphoneMediaEncryptionSRTP); + + CU_ASSERT_TRUE(call(pauline,marie)); + + CU_ASSERT_TRUE(add_video(pauline,marie)); + wait_for_until(pauline->lc,marie->lc,&dummy,1,1000); /* Wait for VFU request exchanges to be finished. */ + CU_ASSERT_TRUE(remove_video(pauline,marie)); + CU_ASSERT_TRUE(add_video(pauline,marie)); + wait_for_until(pauline->lc,marie->lc,&dummy,1,1000); /* Wait for VFU request exchanges to be finished. */ + CU_ASSERT_TRUE(remove_video(pauline,marie)); + /*just to sleep*/ + linphone_core_terminate_all_calls(pauline->lc); + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1)); + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1)); + } else { + ms_warning("Not tested because SRTP is not available."); + } + + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + static void call_with_declined_video_base(bool_t using_policy) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); - LinphoneCallParams* callee_params; + LinphoneCallParams* callee_params=NULL; LinphoneCallParams* caller_params; LinphoneCall* marie_call; LinphoneCall* pauline_call; @@ -1184,11 +1331,16 @@ static void call_with_declined_video_base(bool_t using_policy) { caller_params=linphone_core_create_default_call_parameters(pauline->lc); if (!using_policy) linphone_call_params_enable_video(caller_params,TRUE); - callee_params=linphone_core_create_default_call_parameters(marie->lc); - if (!using_policy) + + if (!using_policy){ + callee_params=linphone_core_create_default_call_parameters(marie->lc); linphone_call_params_enable_video(callee_params,FALSE); + } - CU_ASSERT_TRUE(call_with_params(pauline,marie,caller_params,callee_params)); + CU_ASSERT_TRUE(call_with_params2(pauline,marie,caller_params,callee_params,using_policy)); + + linphone_call_params_destroy(caller_params); + if (callee_params) linphone_call_params_destroy(callee_params); marie_call=linphone_core_get_current_call(marie->lc); pauline_call=linphone_core_get_current_call(pauline->lc); @@ -1211,7 +1363,7 @@ static void call_with_declined_video_using_policy(void) { } static void video_call_base(LinphoneCoreManager* pauline,LinphoneCoreManager* marie, bool_t using_policy) { - LinphoneCallParams* callee_params; + LinphoneCallParams* callee_params=NULL; LinphoneCallParams* caller_params; LinphoneCall* marie_call; LinphoneCall* pauline_call; @@ -1234,16 +1386,18 @@ static void video_call_base(LinphoneCoreManager* pauline,LinphoneCoreManager* ma caller_params=linphone_core_create_default_call_parameters(pauline->lc); if (!using_policy) linphone_call_params_enable_video(caller_params,TRUE); - callee_params=linphone_core_create_default_call_parameters(marie->lc); - if (!using_policy) + + if (!using_policy){ + callee_params=linphone_core_create_default_call_parameters(marie->lc); linphone_call_params_enable_video(callee_params,TRUE); + } - CU_ASSERT_TRUE(call_with_params(pauline,marie,caller_params,callee_params)); + CU_ASSERT_TRUE(call_with_params2(pauline,marie,caller_params,callee_params,using_policy)); marie_call=linphone_core_get_current_call(marie->lc); pauline_call=linphone_core_get_current_call(pauline->lc); linphone_call_params_destroy(caller_params); - linphone_call_params_destroy(callee_params); + if (callee_params) linphone_call_params_destroy(callee_params); if (marie_call && pauline_call ) { CU_ASSERT_TRUE(linphone_call_log_video_enabled(linphone_call_get_call_log(marie_call))); @@ -1911,8 +2065,8 @@ static void early_media_call_with_update_base(bool_t media_change){ lcs = ms_list_append(lcs,marie->lc); lcs = ms_list_append(lcs,pauline->lc); if (media_change) { - disable_all_codecs_except_one(marie->lc,"pcmu"); - disable_all_codecs_except_one(pauline->lc,"pcmu"); + disable_all_audio_codecs_except_one(marie->lc,"pcmu",-1); + disable_all_audio_codecs_except_one(pauline->lc,"pcmu",-1); } /* @@ -1937,8 +2091,8 @@ static void early_media_call_with_update_base(bool_t media_change){ pauline_params = linphone_call_params_copy(linphone_call_get_current_params(pauline_call)); if (media_change) { - disable_all_codecs_except_one(marie->lc,"pcma"); - disable_all_codecs_except_one(pauline->lc,"pcma"); + disable_all_audio_codecs_except_one(marie->lc,"pcma",-1); + disable_all_audio_codecs_except_one(pauline->lc,"pcma",-1); } #define UPDATED_SESSION_NAME "nouveau nom de session" @@ -2143,6 +2297,10 @@ static void call_transfer_existing_call_outgoing_call(void) { MSList* lcs=ms_list_append(NULL,marie->lc); const MSList* calls; + + linphone_core_use_files (pauline->lc,TRUE); + linphone_core_use_files (laure->lc,TRUE); + lcs=ms_list_append(lcs,pauline->lc); lcs=ms_list_append(lcs,laure->lc); @@ -2157,7 +2315,7 @@ static void call_transfer_existing_call_outgoing_call(void) { CU_ASSERT_TRUE(call(marie,laure)); marie_call_laure=linphone_core_get_current_call(marie->lc); laure_called_by_marie=linphone_core_get_current_call(laure->lc); - /*marie pause pauline*/ + /*marie pause laure*/ CU_ASSERT_TRUE(pause_call_1(marie,marie_call_laure,laure,laure_called_by_marie)); reset_counters(&marie->stat); @@ -2412,7 +2570,9 @@ static void call_rejected_because_wrong_credentials_with_params(const char* user linphone_core_set_user_agent(marie->lc,user_agent,NULL); } if (!enable_auth_req_cb) { - marie->lc->vtable.auth_info_requested=NULL; + + ((LinphoneCoreVTable*)(marie->lc->vtables->data))->auth_info_requested=NULL; + linphone_core_add_auth_info(marie->lc,wrong_auth_info); } @@ -2647,6 +2807,183 @@ static void savpf_to_savpf_call(void) { profile_call(TRUE, TRUE, TRUE, TRUE, "RTP/SAVPF"); } +static char *create_filepath(const char *dir, const char *filename, const char *ext) { + char *filepath = ms_new0(char, strlen(dir) + strlen(filename) + strlen(ext) + 3); + strcpy(filepath, dir); + strcat(filepath, "/"); + strcat(filepath, filename); + strcat(filepath, "."); + strcat(filepath, ext); + return filepath; +} + +static void record_call(const char *filename, bool_t enableVideo) { + LinphoneCoreManager *marie = NULL; + LinphoneCoreManager *pauline = NULL; + LinphoneCallParams *marieParams = NULL; + LinphoneCallParams *paulineParams = NULL; + LinphoneCall *callInst = NULL; + const char **formats, *format; + char *filepath; + int dummy=0, i; + +#if defined(HAVE_OPENH264) && defined(ANDROID) + ms_init(); + libmsopenh264_init(); +#endif + + + marie = linphone_core_manager_new("marie_h264_rc"); + pauline = linphone_core_manager_new("pauline_h264_rc"); + marieParams = linphone_core_create_default_call_parameters(marie->lc); + paulineParams = linphone_core_create_default_call_parameters(pauline->lc); + +#ifdef VIDEO_ENABLED + if(enableVideo) { + if((linphone_core_find_payload_type(marie->lc, "H264", -1, -1) != NULL) + && (linphone_core_find_payload_type(pauline->lc, "H264", -1, -1) != NULL)) { + linphone_call_params_enable_video(marieParams, TRUE); + linphone_call_params_enable_video(paulineParams, TRUE); + disable_all_video_codecs_except_one(marie->lc, "H264"); + disable_all_video_codecs_except_one(pauline->lc, "H264"); + } else { + ms_warning("call_recording(): the H264 payload has not been found. Only sound will be recorded"); + } + } +#endif + + formats = linphone_core_get_supported_file_formats(marie->lc); + + for(i=0, format = formats[0]; format != NULL; i++, format = formats[i]) { + filepath = create_filepath(liblinphone_tester_writable_dir_prefix, filename, format); + remove(filepath); + linphone_call_params_set_record_file(marieParams, filepath); + if((CU_ASSERT_TRUE(call_with_params(marie, pauline, marieParams, paulineParams))) + && (CU_ASSERT_PTR_NOT_NULL(callInst = linphone_core_get_current_call(marie->lc)))) { + + ms_message("call_recording(): start recording into %s", filepath); + linphone_call_start_recording(callInst); + wait_for_until(marie->lc,pauline->lc,&dummy,1,5000); + linphone_call_stop_recording(callInst); + end_call(marie, pauline); + CU_ASSERT_EQUAL(access(filepath, F_OK), 0); + remove(filepath); + } + ms_free(filepath); + } + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +#if defined(HAVE_OPENH264) && defined(ANDROID) + ms_exit(); +#endif +} + +static void audio_call_recording_test(void) { + record_call("recording", FALSE); +} + +#ifdef VIDEO_ENABLED +static void video_call_recording_test(void) { + record_call("recording", TRUE); +} + +static void video_call_snapshot(void) { + LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_rc"); + LinphoneCallParams *marieParams = linphone_core_create_default_call_parameters(marie->lc); + LinphoneCallParams *paulineParams = linphone_core_create_default_call_parameters(pauline->lc); + LinphoneCall *callInst = NULL; + char *filename = create_filepath(liblinphone_tester_writable_dir_prefix, "snapshot", "jpeg"); + int dummy = 0; + + linphone_core_enable_video_capture(marie->lc, TRUE); + linphone_core_enable_video_display(marie->lc, TRUE); + linphone_core_enable_video_capture(pauline->lc, TRUE); + linphone_core_enable_video_display(pauline->lc, FALSE); + linphone_call_params_enable_video(marieParams, TRUE); + linphone_call_params_enable_video(paulineParams, TRUE); + + if((CU_ASSERT_TRUE(call_with_params(marie, pauline, marieParams, paulineParams))) + && (CU_ASSERT_PTR_NOT_NULL(callInst = linphone_core_get_current_call(marie->lc)))) { + linphone_call_take_video_snapshot(callInst, filename); + wait_for_until(marie->lc, pauline->lc, &dummy, 1, 5000); + CU_ASSERT_EQUAL(access(filename, F_OK), 0); + remove(filename); + } + ms_free(filename); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + +#endif + +static void call_with_in_dialog_update(void) { + int begin; + int leaked_objects; + LinphoneCoreManager* marie; + LinphoneCoreManager* pauline; + LinphoneCallParams *params; + + belle_sip_object_enable_leak_detector(TRUE); + begin=belle_sip_object_get_object_count(); + + marie = linphone_core_manager_new( "marie_rc"); + pauline = linphone_core_manager_new( "pauline_rc"); + CU_ASSERT_TRUE(call(pauline,marie)); + liblinphone_tester_check_rtcp(marie,pauline); + params=linphone_core_create_call_params(marie->lc,linphone_core_get_current_call(marie->lc)); + params->no_user_consent=TRUE; + linphone_core_update_call(marie->lc,linphone_core_get_current_call(marie->lc),params); + linphone_call_params_destroy(params); + CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallUpdating,1)); + CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,2)); + CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallUpdatedByRemote,1)); + CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,2)); + end_call(marie,pauline); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + + leaked_objects=belle_sip_object_get_object_count()-begin; + CU_ASSERT_TRUE(leaked_objects==0); + if (leaked_objects>0){ + belle_sip_object_dump_active_objects(); + } +} + +static void call_with_custom_supported_tags(void) { + int begin; + int leaked_objects; + LinphoneCoreManager* marie; + LinphoneCoreManager* pauline; + const LinphoneCallParams *remote_params; + const char *recv_supported; + + belle_sip_object_enable_leak_detector(TRUE); + begin=belle_sip_object_get_object_count(); + + marie = linphone_core_manager_new( "marie_rc"); + pauline = linphone_core_manager_new( "pauline_rc"); + + linphone_core_add_supported_tag(marie->lc,"pouet-tag"); + CU_ASSERT_TRUE(call(pauline,marie)); + liblinphone_tester_check_rtcp(marie,pauline); + remote_params=linphone_call_get_remote_params(linphone_core_get_current_call(pauline->lc)); + recv_supported=linphone_call_params_get_custom_header(remote_params,"supported"); + CU_ASSERT_PTR_NOT_NULL(recv_supported); + if (recv_supported){ + CU_ASSERT_TRUE(strstr(recv_supported,"pouet-tag")!=NULL); + } + end_call(marie,pauline); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + + leaked_objects=belle_sip_object_get_object_count()-begin; + CU_ASSERT_TRUE(leaked_objects==0); + if (leaked_objects>0){ + belle_sip_object_dump_active_objects(); + } +} + test_t call_tests[] = { { "Early declined call", early_declined_call }, { "Call declined", call_declined }, @@ -2657,6 +2994,7 @@ test_t call_tests[] = { { "Call failed because of codecs", call_failed_because_of_codecs }, { "Simple call", simple_call }, { "Outbound call with multiple proxy possible", call_outbound_with_multiple_proxy }, + { "Audio call recording", audio_call_recording_test }, #if 0 /* not yet activated because not implemented */ { "Multiple answers to a call", multiple_answers_call }, #endif @@ -2685,12 +3023,16 @@ test_t call_tests[] = { { "ZRTP ice video call", zrtp_video_ice_call }, { "Call with video added", call_with_video_added }, { "Call with video added (random ports)", call_with_video_added_random_ports }, + { "Call with several video switches", call_with_several_video_switches }, + { "SRTP call with several video switches", srtp_call_with_several_video_switches }, { "Call with video declined", call_with_declined_video}, { "Call with video declined using policy", call_with_declined_video_using_policy}, { "Call with multiple early media", multiple_early_media }, { "Call with ICE from video to non-video", call_with_ice_video_to_novideo}, { "Call with ICE and video added", call_with_ice_video_added }, { "Video call with ICE no matching audio codecs", video_call_with_ice_no_matching_audio_codecs }, + { "Video call recording", video_call_recording_test }, + { "Snapshot", video_call_snapshot }, #endif { "SRTP ice call", srtp_ice_call }, { "ZRTP ice call", zrtp_ice_call }, @@ -2735,7 +3077,9 @@ test_t call_tests[] = { { "SAVPF to AVP call", savpf_to_avp_call }, { "SAVPF to AVPF call", savpf_to_avpf_call }, { "SAVPF to SAVP call", savpf_to_savp_call }, - { "SAVPF to SAVPF call", savpf_to_savpf_call } + { "SAVPF to SAVPF call", savpf_to_savpf_call }, + { "Call with in-dialog UPDATE request", call_with_in_dialog_update }, + { "Call with custom supported tags", call_with_custom_supported_tags } }; test_suite_t call_test_suite = { diff --git a/tester/flexisip.conf b/tester/flexisip/flexisip.conf similarity index 99% rename from tester/flexisip.conf rename to tester/flexisip/flexisip.conf index 303a1022f..12f42d945 100755 --- a/tester/flexisip.conf +++ b/tester/flexisip/flexisip.conf @@ -151,7 +151,7 @@ db-implementation=file # for a DSN-less connection. ex3: /etc/flexisip/passwd; for a file # containing one 'user@domain password' by line. # Default value: -datasource=/etc/flexisip/userdb.conf +datasource=./flexisip/userdb.conf # Odbc SQL request to execute to obtain the password # . Named parameters are :id (the user found in the from header), diff --git a/tester/userdb.conf b/tester/flexisip/userdb.conf similarity index 100% rename from tester/userdb.conf rename to tester/flexisip/userdb.conf diff --git a/tester/liblinphone_tester.c b/tester/liblinphone_tester.c index b11cbefaf..5fb91605c 100644 --- a/tester/liblinphone_tester.c +++ b/tester/liblinphone_tester.c @@ -27,9 +27,6 @@ #ifdef ANDROID -extern void AndroidPrintf(FILE *stream, const char *fmt, ...); -#define fprintf(file, fmt, ...) AndroidPrintf(file, fmt, ##__VA_ARGS__) - #include #include #include @@ -118,8 +115,9 @@ static void liblinphone_tester_qnx_log_handler(OrtpLogLevel lev, const char *fmt #endif /* __QNX__ */ + void helper(const char *name) { - fprintf(stderr,"%s --help\n" + liblinphone_tester_fprintf(stderr,"%s --help\n" "\t\t\t--verbose\n" "\t\t\t--silent\n" "\t\t\t--list-suites\n" @@ -197,7 +195,7 @@ int main (int argc, char *argv[]) liblinphone_tester_list_suite_tests(suite_name); return 0; } else { - fprintf(stderr, "Unknown option \"%s\"\n", argv[i]); \ + liblinphone_tester_fprintf(stderr, "Unknown option \"%s\"\n", argv[i]); \ helper(argv[0]); return -1; } diff --git a/tester/liblinphone_tester.h b/tester/liblinphone_tester.h index 8fbeafc31..67b68f87c 100644 --- a/tester/liblinphone_tester.h +++ b/tester/liblinphone_tester.h @@ -58,6 +58,7 @@ extern test_suite_t flexisip_test_suite; extern test_suite_t stun_test_suite; extern test_suite_t remote_provisioning_test_suite; extern test_suite_t quality_reporting_test_suite; +extern test_suite_t transport_test_suite; extern int liblinphone_tester_nb_test_suites(void); @@ -192,6 +193,8 @@ typedef struct _stats { int number_of_LinphoneCallEncryptedOn; int number_of_LinphoneCallEncryptedOff; + int number_of_NetworkReachableTrue; + int number_of_NetworkReachableFalse; LinphoneChatMessage* last_received_chat_message; }stats; @@ -239,6 +242,7 @@ bool_t call_with_params(LinphoneCoreManager* caller_mgr , const LinphoneCallParams *caller_params , const LinphoneCallParams *callee_params); bool_t call(LinphoneCoreManager* caller_mgr,LinphoneCoreManager* callee_mgr); +void end_call(LinphoneCoreManager *m1, LinphoneCoreManager *m2); stats * get_stats(LinphoneCore *lc); LinphoneCoreManager *get_manager(LinphoneCore *lc); const char *liblinphone_tester_get_subscribe_content(void); @@ -247,6 +251,10 @@ void liblinphone_tester_chat_message_state_change(LinphoneChatMessage* msg,Linph void liblinphone_tester_check_rtcp(LinphoneCoreManager* caller, LinphoneCoreManager* callee); void liblinphone_tester_clock_start(MSTimeSpec *start); bool_t liblinphone_tester_clock_elapsed(const MSTimeSpec *start, int value_ms); +#ifdef ANDROID +void cunit_android_trace_handler(int level, const char *fmt, va_list args) ; +#endif +int liblinphone_tester_fprintf(FILE * stream, const char * format, ...); #endif /* LIBLINPHONE_TESTER_H_ */ diff --git a/tester/message_tester.c b/tester/message_tester.c index 4ddd13390..ef5f819b5 100644 --- a/tester/message_tester.c +++ b/tester/message_tester.c @@ -47,11 +47,11 @@ void message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMess ms_free(from); counters = get_stats(lc); counters->number_of_LinphoneMessageReceived++; - if (linphone_chat_message_get_file_transfer_information(message)) - counters->number_of_LinphoneMessageReceivedWithFile++; if (counters->last_received_chat_message) linphone_chat_message_unref(counters->last_received_chat_message); - linphone_chat_message_ref(counters->last_received_chat_message=message); - if (linphone_chat_message_get_external_body_url(message)) { + counters->last_received_chat_message=linphone_chat_message_ref(message); + if (linphone_chat_message_get_file_transfer_information(message)) { + counters->number_of_LinphoneMessageReceivedWithFile++; + } else if (linphone_chat_message_get_external_body_url(message)) { counters->number_of_LinphoneMessageExtBodyReceived++; if (message_external_body_url) { CU_ASSERT_STRING_EQUAL(linphone_chat_message_get_external_body_url(message),message_external_body_url); @@ -67,19 +67,16 @@ void file_transfer_received(LinphoneCore *lc, LinphoneChatMessage *message, cons FILE* file=NULL; char receive_file[256]; snprintf(receive_file,sizeof(receive_file), "%s/receive_file.dump", liblinphone_tester_writable_dir_prefix); - if (!linphone_chat_message_get_user_data(message)) { /*first chunk, creating file*/ - file = fopen("receive_file.dump","wb"); + file = fopen(receive_file,"wb"); linphone_chat_message_set_user_data(message,(void*)file); /*store fd for next chunks*/ } else { /*next chunk*/ file = (FILE*)linphone_chat_message_get_user_data(message); - if (size==0) { /* tranfer complerte */ + if (size==0) { /* tranfer complete */ stats* counters = get_stats(lc); - linphone_chat_room_destroy(linphone_chat_message_get_chat_room(message)); - linphone_chat_message_destroy(message); counters->number_of_LinphoneMessageExtBodyReceived++; fclose(file); } else { /* store content on a file*/ @@ -125,7 +122,7 @@ void file_transfer_progress_indication(LinphoneCore *lc, LinphoneChatMessage *me const LinphoneAddress* to_address = linphone_chat_message_get_to(message); char *address = linphone_chat_message_is_outgoing(message)?linphone_address_as_string(to_address):linphone_address_as_string(from_address); stats* counters = get_stats(lc); - printf(" File transfer [%d%%] %s of type [%s/%s] %s [%s] \n", (int)progress + ms_message(" File transfer [%d%%] %s of type [%s/%s] %s [%s] \n", (int)progress ,(linphone_chat_message_is_outgoing(message)?"sent":"received") , content->type , content->subtype @@ -158,6 +155,9 @@ void liblinphone_tester_chat_message_state_change(LinphoneChatMessage* msg,Linph case LinphoneChatMessageStateInProgress: counters->number_of_LinphoneMessageInProgress++; break; + case LinphoneChatMessageStateFileTransferError: + counters->number_of_LinphoneMessageNotDelivered++; + break; default: ms_error("Unexpected state [%s] for message [%p]",linphone_chat_message_state_to_string(state),msg); } @@ -175,7 +175,12 @@ static void text_message(void) { char* to = linphone_address_as_string(marie->identity); LinphoneChatRoom* chat_room = linphone_core_create_chat_room(pauline->lc,to); ms_free(to); - + { + int dummy=0; + wait_for_until(marie->lc,pauline->lc,&dummy,1,100); /*just to have time to purge message stored in the server*/ + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + } linphone_chat_room_send_message(chat_room,"Bla bla bla bla"); CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1)); CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageReceivedLegacy,1); @@ -201,7 +206,12 @@ static void text_message_within_dialog(void) { to = linphone_address_as_string(marie->identity); chat_room = linphone_core_create_chat_room(pauline->lc,to); ms_free(to); - + { + int dummy=0; + wait_for_until(marie->lc,pauline->lc,&dummy,1,100); /*just to have time to purge message stored in the server*/ + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + } CU_ASSERT_TRUE(call(marie,pauline)); linphone_chat_room_send_message(chat_room,"Bla bla bla bla"); @@ -215,12 +225,9 @@ static void text_message_within_dialog(void) { static LinphoneAuthInfo* text_message_with_credential_from_auth_cb_auth_info; static void text_message_with_credential_from_auth_cb_auth_info_requested(LinphoneCore *lc, const char *realm, const char *username, const char *domain) { - stats* counters; ms_message("text_message_with_credential_from_auth_cb:Auth info requested for user id [%s] at realm [%s]\n" ,username ,realm); - counters = get_stats(lc); - counters->number_of_auth_info_requested++; linphone_core_add_auth_info(lc,text_message_with_credential_from_auth_cb_auth_info); /*add stored authentication info to LinphoneCore*/ } @@ -228,6 +235,7 @@ static void text_message_with_credential_from_auth_cb_auth_info_requested(Linpho static void text_message_with_credential_from_auth_cb(void) { char* to; LinphoneChatRoom* chat_room; + LinphoneCoreVTable* vtable = linphone_vtable_new(); LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); text_message_with_credential_from_auth_cb_auth_info=linphone_auth_info_clone((LinphoneAuthInfo*)(linphone_core_get_auth_info_list(marie->lc)->data)); @@ -238,13 +246,18 @@ static void text_message_with_credential_from_auth_cb(void) { /*to force cb to be called*/ linphone_core_clear_all_auth_info(marie->lc); - marie->lc->vtable.auth_info_requested=text_message_with_credential_from_auth_cb_auth_info_requested; + vtable->auth_info_requested=text_message_with_credential_from_auth_cb_auth_info_requested; + linphone_core_add_listener(marie->lc, vtable); to = linphone_address_as_string(marie->identity); chat_room = linphone_core_create_chat_room(pauline->lc,to); ms_free(to); - - + { + int dummy=0; + wait_for_until(marie->lc,pauline->lc,&dummy,1,100); /*just to have time to purge message stored in the server*/ + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + } linphone_chat_room_send_message(chat_room,"Bla bla bla bla"); CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1)); CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageReceivedLegacy,1); @@ -272,8 +285,13 @@ static void text_message_with_privacy(void) { linphone_core_get_default_proxy(pauline->lc,&pauline_proxy); linphone_proxy_config_set_privacy(pauline_proxy,LinphonePrivacyId); - CU_ASSERT_PTR_NULL(linphone_core_get_chat_room(marie->lc,pauline->identity)); - + CU_ASSERT_PTR_NOT_NULL(linphone_core_get_chat_room(marie->lc,pauline->identity)); + { + int dummy=0; + wait_for_until(marie->lc,pauline->lc,&dummy,1,100); /*just to have time to purge message stored in the server*/ + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + } linphone_chat_room_send_message(chat_room,"Bla bla bla bla"); CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1)); CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageReceivedLegacy,1); @@ -318,6 +336,12 @@ static void text_message_compatibility_mode(void) { CU_ASSERT_TRUE (wait_for(marie->lc,marie->lc,&marie->stat.number_of_LinphoneRegistrationOk,1)); chat_room = linphone_core_create_chat_room(marie->lc,to); + { + int dummy=0; + wait_for_until(marie->lc,pauline->lc,&dummy,1,100); /*just to have time to purge message stored in the server*/ + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + } linphone_chat_room_send_message(chat_room,"Bla bla bla bla"); CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageReceived,1)); CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageReceivedLegacy,1); @@ -326,22 +350,41 @@ static void text_message_compatibility_mode(void) { } static void text_message_with_ack(void) { + int leaked_objects; + int begin; + belle_sip_object_enable_leak_detector(TRUE); + begin=belle_sip_object_get_object_count(); + LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); /* make sure lime is not enabled */ linphone_core_set_lime(marie->lc, 0); linphone_core_set_lime(pauline->lc, 0); - - char* to = linphone_address_as_string(marie->identity); - LinphoneChatRoom* chat_room = linphone_core_create_chat_room(pauline->lc,to); - LinphoneChatMessage* message = linphone_chat_room_create_message(chat_room,"Bli bli bli \n blu"); - linphone_chat_room_send_message2(chat_room,message,liblinphone_tester_chat_message_state_change,pauline->lc); - CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1)); - CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageDelivered,1)); - CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,1); - linphone_core_manager_destroy(marie); - linphone_core_manager_destroy(pauline); + { + LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); + char* to = linphone_address_as_string(marie->identity); + LinphoneChatRoom* chat_room = linphone_core_create_chat_room(pauline->lc,to); + LinphoneChatMessage* message = linphone_chat_room_create_message(chat_room,"Bli bli bli \n blu"); + { + int dummy=0; + wait_for_until(marie->lc,pauline->lc,&dummy,1,100); /*just to have time to purge message stored in the server*/ + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + } + linphone_chat_room_send_message2(chat_room,message,liblinphone_tester_chat_message_state_change,pauline->lc); + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1)); + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageDelivered,1)); + CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,1); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + } + leaked_objects=belle_sip_object_get_object_count()-begin; + CU_ASSERT_TRUE(leaked_objects==0); + if (leaked_objects>0){ + belle_sip_object_dump_active_objects(); + } } static void text_message_with_external_body(void) { @@ -356,6 +399,12 @@ static void text_message_with_external_body(void) { LinphoneChatRoom* chat_room = linphone_core_create_chat_room(pauline->lc,to); LinphoneChatMessage* message = linphone_chat_room_create_message(chat_room,"Bli bli bli \n blu"); linphone_chat_message_set_external_body_url(message,message_external_body_url="http://www.linphone.org"); + { + int dummy=0; + wait_for_until(marie->lc,pauline->lc,&dummy,1,100); /*just to have time to purge message stored in the server*/ + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + } linphone_chat_room_send_message2(chat_room,message,liblinphone_tester_chat_message_state_change,pauline->lc); /* check transient message list: the message should be in it, and should be the only one */ @@ -466,22 +515,28 @@ static void lime_file_transfer_message(void) { content.size=sizeof(big_file); /*total size to be transfered*/ content.name = "bigfile.txt"; message = linphone_chat_room_create_file_transfer_message(chat_room, &content); - + { + int dummy=0; + wait_for_until(marie->lc,pauline->lc,&dummy,1,100); /*just to have time to purge message stored in the server*/ + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + } linphone_chat_room_send_message2(chat_room,message,liblinphone_tester_chat_message_state_change,pauline->lc); CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedWithFile,1)); - if (marie->stat.last_received_info_message ) { - linphone_chat_message_start_file_download((const LinphoneChatMessage*)marie->stat.last_received_info_message); + if (marie->stat.last_received_chat_message ) { + linphone_chat_message_start_file_download(marie->stat.last_received_chat_message, liblinphone_tester_chat_message_state_change); } - CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageDelivered,1)); + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageExtBodyReceived,1)); CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,1); + CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageDelivered,1); CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageExtBodyReceived,1); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } -static void file_transfer_message_io_error(void) { +static void file_transfer_message_io_error_upload(void) { int i; char* to; LinphoneChatRoom* chat_room; @@ -514,7 +569,12 @@ static void file_transfer_message_io_error(void) { content.size=sizeof(big_file); /*total size to be transfered*/ content.name = "bigfile.txt"; message = linphone_chat_room_create_file_transfer_message(chat_room, &content); - + { + int dummy=0; + wait_for_until(marie->lc,pauline->lc,&dummy,1,100); /*just to have time to purge message stored in the server*/ + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + } linphone_chat_room_send_message2(chat_room,message,liblinphone_tester_chat_message_state_change,pauline->lc); /*wait for file to be 25% uploaded and simultate a network error*/ @@ -527,10 +587,199 @@ static void file_transfer_message_io_error(void) { CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageExtBodyReceived,0); sal_set_send_error(pauline->lc->sal, 0); + + linphone_core_refresh_registers(pauline->lc); /*to make sure registration is back in registered and so it can be later unregistered*/ + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneRegistrationOk,pauline->stat.number_of_LinphoneRegistrationOk+1)); + linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } + +#ifdef TEST_IS_BUGGED_NO_CALL_TO_IO_ERROR_CALLBACK +static void file_transfer_message_io_error_download(void) { + int i; + char* to; + LinphoneChatRoom* chat_room; + LinphoneChatMessage* message; + LinphoneContent content; + const char* big_file_content="big file"; /* setting dummy file content to something */ + LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + + /* setting dummy file content to something */ + for (i=0;ilc,"https://www.linphone.org:444/lft.php"); + + /* create a chatroom on pauline's side */ + to = linphone_address_as_string(marie->identity); + chat_room = linphone_core_create_chat_room(pauline->lc,to); + + /* create a file transfer message */ + memset(&content,0,sizeof(content)); + content.type="text"; + content.subtype="plain"; + content.size=sizeof(big_file); /*total size to be transfered*/ + content.name = "bigfile.txt"; + message = linphone_chat_room_create_file_transfer_message(chat_room, &content); + { + int dummy=0; + wait_for_until(marie->lc,pauline->lc,&dummy,1,100); /*just to have time to purge message stored in the server*/ + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + } + linphone_chat_room_send_message2(chat_room,message,liblinphone_tester_chat_message_state_change,pauline->lc); + + /* wait for marie to receive pauline's message */ + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedWithFile,1)); + + + if (marie->stat.last_received_chat_message ) { /* get last message and use it to download file */ + linphone_chat_message_start_file_download(marie->stat.last_received_chat_message, liblinphone_tester_chat_message_state_change); + /* wait for file to be 50% downloaded */ + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.progress_of_LinphoneFileTransfer, 50)); + /* and simulate network error */ + sal_set_recv_error(marie->lc->sal, -1); + } + + CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,1); + CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageDelivered,1); + CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageNotDelivered,1); + CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageExtBodyReceived,0); + + sal_set_recv_error(marie->lc->sal, 0); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} +#endif + +static void file_transfer_message_upload_cancelled(void) { + int i; + char* to; + LinphoneChatRoom* chat_room; + LinphoneChatMessage* message; + LinphoneContent content; + const char* big_file_content="big file"; /* setting dummy file content to something */ + LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + + /* setting dummy file content to something */ + for (i=0;ilc,"https://www.linphone.org:444/lft.php"); + + /* create a chatroom on pauline's side */ + to = linphone_address_as_string(marie->identity); + chat_room = linphone_core_create_chat_room(pauline->lc,to); + + /* create a file transfer message */ + memset(&content,0,sizeof(content)); + content.type="text"; + content.subtype="plain"; + content.size=sizeof(big_file); /*total size to be transfered*/ + content.name = "bigfile.txt"; + message = linphone_chat_room_create_file_transfer_message(chat_room, &content); + { + int dummy=0; + wait_for_until(marie->lc,pauline->lc,&dummy,1,100); /*just to have time to purge message stored in the server*/ + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + } + linphone_chat_room_send_message2(chat_room,message,liblinphone_tester_chat_message_state_change,pauline->lc); + + /*wait for file to be 50% uploaded and cancel the transfer */ + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.progress_of_LinphoneFileTransfer, 50)); + linphone_chat_room_cancel_file_transfer(message); + + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageNotDelivered,1)); + + CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageNotDelivered,1); + CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageExtBodyReceived,0); + + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + +static void file_transfer_message_download_cancelled(void) { +#if 0 + int i; + char* to; + LinphoneChatRoom* chat_room; + LinphoneChatMessage* message; + LinphoneContent content; + const char* big_file_content="big file"; /* setting dummy file content to something */ + LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + + /* setting dummy file content to something */ + for (i=0;ilc,"https://www.linphone.org:444/lft.php"); + + /* create a chatroom on pauline's side */ + to = linphone_address_as_string(marie->identity); + chat_room = linphone_core_create_chat_room(pauline->lc,to); + + /* create a file transfer message */ + memset(&content,0,sizeof(content)); + content.type="text"; + content.subtype="plain"; + content.size=sizeof(big_file); /*total size to be transfered*/ + content.name = "bigfile.txt"; + message = linphone_chat_room_create_file_transfer_message(chat_room, &content); + { + int dummy=0; + wait_for_until(marie->lc,pauline->lc,&dummy,1,100); /*just to have time to purge message stored in the server*/ + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + } + linphone_chat_room_send_message2(chat_room,message,liblinphone_tester_chat_message_state_change,pauline->lc); + + /* wait for marie to receive pauline's message */ + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedWithFile,1)); + + + if (marie->stat.last_received_chat_message ) { /* get last message and use it to download file */ + linphone_chat_message_start_file_download(marie->stat.last_received_chat_message, liblinphone_tester_chat_message_state_change); + /* wait for file to be 50% downloaded */ + CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.progress_of_LinphoneFileTransfer, 50)); + /* and cancel the transfer */ + linphone_chat_room_cancel_file_transfer(marie->stat.last_received_chat_message); + } + + CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,1); + CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageDelivered,1); + CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageExtBodyReceived,0); + CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageNotDelivered,1); + + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +#endif + ms_error("Test skipped"); +} + static void text_message_with_send_error(void) { LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); @@ -547,6 +796,12 @@ static void text_message_with_send_error(void) { /*simultate a network error*/ sal_set_send_error(marie->lc->sal, -1); + { + int dummy=0; + wait_for_until(marie->lc,pauline->lc,&dummy,1,100); /*just to have time to purge message stored in the server*/ + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + } linphone_chat_room_send_message2(chat_room,message,liblinphone_tester_chat_message_state_change,marie->lc); /* check transient message list: the message should be in it, and should be the only one */ @@ -577,12 +832,15 @@ static void text_message_denied(void) { char* to = linphone_address_as_string(pauline->identity); LinphoneChatRoom* chat_room = linphone_core_create_chat_room(marie->lc,to); LinphoneChatMessage* message = linphone_chat_room_create_message(chat_room,"Bli bli bli \n blu"); - reset_counters(&marie->stat); - reset_counters(&pauline->stat); /*pauline doesn't want to be disturbed*/ linphone_core_disable_chat(pauline->lc,LinphoneReasonDoNotDisturb); - + { + int dummy=0; + wait_for_until(marie->lc,pauline->lc,&dummy,1,100); /*just to have time to purge message stored in the server*/ + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + } linphone_chat_room_send_message2(chat_room,message,liblinphone_tester_chat_message_state_change,marie->lc); CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageNotDelivered,1)); @@ -630,6 +888,12 @@ static void info_message_with_args(bool_t with_content) { ct.size=strlen(info_content); linphone_info_message_set_content(info,&ct); } + { + int dummy=0; + wait_for_until(marie->lc,pauline->lc,&dummy,1,100); /*just to have time to purge message stored in the server*/ + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + } linphone_call_send_info_message(linphone_core_get_current_call(marie->lc),info); linphone_info_message_destroy(info); @@ -680,6 +944,12 @@ static void is_composing_notification(void) { int dummy = 0; ms_free(to); + { + int dummy=0; + wait_for_until(marie->lc,pauline->lc,&dummy,1,100); /*just to have time to purge message stored in the server*/ + reset_counters(&marie->stat); + reset_counters(&pauline->stat); + } linphone_chat_room_compose(chat_room); wait_for_until(pauline->lc, marie->lc, &dummy, 1, 1500); /*just to sleep while iterating*/ linphone_chat_room_send_message(chat_room, "Composing a message"); @@ -885,12 +1155,11 @@ static void lime_text_message(void) { /* * Copy file "from" to file "to". * Destination file is truncated if existing. - * Return 1 on success, 0 on error (printing an error). + * Return 0 on success, positive value on error. */ static int message_tester_copy_file(const char *from, const char *to) { - char message[256]; FILE *in, *out; char buf[256]; size_t n; @@ -899,21 +1168,17 @@ message_tester_copy_file(const char *from, const char *to) in=fopen(from, "r"); if ( in == NULL ) { - snprintf(message, 255, "Can't open %s for reading: %s\n", - from, strerror(errno)); - fprintf(stderr, "%s", message); - return 0; + ms_error("Can't open %s for reading: %s\n",from,strerror(errno)); + return 1; } /* Open "to" file for writing (will truncate existing files) */ out=fopen(to, "w"); if ( out == NULL ) { - snprintf(message, 255, "Can't open %s for writing: %s\n", - to, strerror(errno)); - fprintf(stderr, "%s", message); + ms_error("Can't open %s for writing: %s\n",to,strerror(errno)); fclose(in); - return 0; + return 2; } /* Copy data from "in" to "out" */ @@ -921,16 +1186,17 @@ message_tester_copy_file(const char *from, const char *to) { if ( ! fwrite(buf, 1, n, out) ) { + ms_error("Could not write in %s: %s\n",to,strerror(errno)); fclose(in); fclose(out); - return 0; + return 3; } } fclose(in); fclose(out); - return 1; + return 0; } static int check_no_strange_time(void* data,int argc, char** argv,char** cNames) { @@ -942,10 +1208,11 @@ static void message_storage_migration() { LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); char src_db[256]; char tmp_db[256]; + MSList* chatrooms; snprintf(src_db,sizeof(src_db), "%s/messages.db", liblinphone_tester_file_prefix); snprintf(tmp_db,sizeof(tmp_db), "%s/tmp.db", liblinphone_tester_writable_dir_prefix); - CU_ASSERT_EQUAL_FATAL(message_tester_copy_file(src_db, tmp_db), 1); + CU_ASSERT_EQUAL_FATAL(message_tester_copy_file(src_db, tmp_db), 0); // enable to test the performances of the migration step //linphone_core_message_storage_set_debug(marie->lc, TRUE); @@ -954,13 +1221,59 @@ static void message_storage_migration() { // This will test the migration procedure linphone_core_set_chat_database_path(marie->lc, tmp_db); - MSList* chatrooms = linphone_core_get_chat_rooms(marie->lc); + chatrooms = linphone_core_get_chat_rooms(marie->lc); CU_ASSERT(ms_list_size(chatrooms) > 0); // check that all messages have been migrated to the UTC time storage CU_ASSERT(sqlite3_exec(marie->lc->db, "SELECT * FROM history WHERE time != '-1';", check_no_strange_time, NULL, NULL) == SQLITE_OK ); + + linphone_core_manager_destroy(marie); + remove(tmp_db); } +static void history_messages_count() { + LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); + LinphoneAddress *jehan_addr = linphone_address_new(""); + LinphoneChatRoom *chatroom; + MSList *messages; + char src_db[256]; + char tmp_db[256]; + snprintf(src_db,sizeof(src_db), "%s/messages.db", liblinphone_tester_file_prefix); + snprintf(tmp_db,sizeof(tmp_db), "%s/tmp.db", liblinphone_tester_writable_dir_prefix); + + CU_ASSERT_EQUAL_FATAL(message_tester_copy_file(src_db, tmp_db), 0); + + linphone_core_set_chat_database_path(marie->lc, tmp_db); + + chatroom = linphone_core_get_chat_room(marie->lc, jehan_addr); + CU_ASSERT_PTR_NOT_NULL(chatroom); + if (chatroom){ + MSList *history=linphone_chat_room_get_history(chatroom,0); + CU_ASSERT_EQUAL(linphone_chat_room_get_history_size(chatroom), 1270); + CU_ASSERT_EQUAL(ms_list_size(history), linphone_chat_room_get_history_size(chatroom)); + /*check the second most recent message*/ + CU_ASSERT_STRING_EQUAL(linphone_chat_message_get_text((LinphoneChatMessage *)history->next->data), "Fore and aft follow each other."); + + /*test offset+limit: retrieve the 42th latest message only and check its content*/ + messages=linphone_chat_room_get_history_range(chatroom, 42, 42); + CU_ASSERT_EQUAL(ms_list_size(messages), 1); + CU_ASSERT_STRING_EQUAL(linphone_chat_message_get_text((LinphoneChatMessage *)messages->data), "If you open yourself to the Tao is intangible and evasive, yet prefers to keep us at the mercy of the kingdom, then all of the streams of hundreds of valleys because of its limitless possibilities."); + + /*test offset without limit*/ + CU_ASSERT_EQUAL(ms_list_size(linphone_chat_room_get_history_range(chatroom, 1265, -1)), 1270-1265); + + /*test limit without offset*/ + CU_ASSERT_EQUAL(ms_list_size(linphone_chat_room_get_history_range(chatroom, 0, 5)), 6); + + /*test invalid start*/ + CU_ASSERT_EQUAL(ms_list_size(linphone_chat_room_get_history_range(chatroom, 1265, 1260)), 1270-1265); + } + linphone_core_manager_destroy(marie); + linphone_address_destroy(jehan_addr); + remove(tmp_db); +} + + #endif test_t message_tests[] = { @@ -973,8 +1286,11 @@ test_t message_tests[] = { { "Text message with send error", text_message_with_send_error }, { "Text message with external body", text_message_with_external_body }, { "File transfer message", file_transfer_message }, + { "File transfer message with io error at upload", file_transfer_message_io_error_upload }, +/* { "File transfer message with io error at download", file_transfer_message_io_error_download },*/ + { "File transfer message upload cancelled", file_transfer_message_upload_cancelled }, + { "File transfer message download cancelled", file_transfer_message_download_cancelled }, { "Lime File transfer message", lime_file_transfer_message }, - { "File transfer message with io error", file_transfer_message_io_error }, { "Text message denied", text_message_denied }, { "Info message", info_message }, { "Info message with body", info_message_with_body }, @@ -983,6 +1299,7 @@ test_t message_tests[] = { { "Lime Text Message", lime_text_message } #ifdef MSG_STORAGE_ENABLED ,{ "Database migration", message_storage_migration } + ,{ "History count", history_messages_count } #endif }; diff --git a/tester/messages.db b/tester/messages.db index 072aed397..30fd10efb 100644 Binary files a/tester/messages.db and b/tester/messages.db differ diff --git a/tester/quality_reporting_tester.c b/tester/quality_reporting_tester.c index b6b449b91..d0ad63968 100644 --- a/tester/quality_reporting_tester.c +++ b/tester/quality_reporting_tester.c @@ -80,11 +80,13 @@ char * on_report_send_verify_metrics(const reporting_content_metrics_t *metrics, CU_ASSERT_PTR_NOT_NULL(body=__strstr(body, "SessionDesc:")); CU_ASSERT_PTR_NOT_NULL(body=__strstr(body, "JitterBuffer:")); CU_ASSERT_PTR_NOT_NULL(body=__strstr(body, "PacketLoss:")); - CU_ASSERT_PTR_NOT_NULL(body=__strstr(body, "QualityEst:")); } if (metrics->rtcp_sr_count+metrics->rtcp_xr_count>0){ CU_ASSERT_PTR_NOT_NULL(body=__strstr(body, "Delay:")); } + if (metrics->rtcp_xr_count){ + CU_ASSERT_PTR_NOT_NULL(body=__strstr(body, "QualityEst:")); + } return body; } @@ -113,16 +115,29 @@ void on_report_send_with_rtcp_xr_both(const LinphoneCall *call, int stream_type, on_report_send_with_rtcp_xr_remote(call,stream_type,content); } -void create_call_for_quality_reporting_tests( +bool_t create_call_for_quality_reporting_tests( LinphoneCoreManager* marie, LinphoneCoreManager* pauline, LinphoneCall** call_marie, - LinphoneCall** call_pauline) { - CU_ASSERT_TRUE(call(pauline,marie)); - *call_marie = linphone_core_get_current_call(marie->lc); - *call_pauline = linphone_core_get_current_call(pauline->lc); - CU_ASSERT_PTR_NOT_NULL(*call_marie); - CU_ASSERT_PTR_NOT_NULL(*call_pauline); + LinphoneCall** call_pauline, + LinphoneCallParams * params_marie, + LinphoneCallParams * params_pauline + ) { + + + bool_t call_succeeded = call_with_params(marie,pauline,params_marie,params_pauline); + CU_ASSERT_TRUE(call_succeeded); + if (call_succeeded) { + if (call_marie) { + *call_marie = linphone_core_get_current_call(marie->lc); + CU_ASSERT_PTR_NOT_NULL(*call_marie); + } + if (call_pauline) { + *call_pauline = linphone_core_get_current_call(pauline->lc); + CU_ASSERT_PTR_NOT_NULL(*call_pauline); + } + } + return call_succeeded; } static void quality_reporting_not_used_without_config() { @@ -131,21 +146,20 @@ static void quality_reporting_not_used_without_config() { LinphoneCall* call_marie = NULL; LinphoneCall* call_pauline = NULL; - create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline); - + if (create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline, NULL, NULL)) { // marie has stats collection enabled but pauline has not - CU_ASSERT_TRUE(linphone_proxy_config_quality_reporting_enabled(call_marie->dest_proxy)); - CU_ASSERT_FALSE(linphone_proxy_config_quality_reporting_enabled(call_pauline->dest_proxy)); + CU_ASSERT_TRUE(linphone_proxy_config_quality_reporting_enabled(call_marie->dest_proxy)); + CU_ASSERT_FALSE(linphone_proxy_config_quality_reporting_enabled(call_pauline->dest_proxy)); - CU_ASSERT_EQUAL(strcmp("sip:collector@sip.example.org", - linphone_proxy_config_get_quality_reporting_collector(call_marie->dest_proxy)), 0); + CU_ASSERT_EQUAL(strcmp("sip:collector@sip.example.org", + linphone_proxy_config_get_quality_reporting_collector(call_marie->dest_proxy)), 0); - // this field should be already filled - CU_ASSERT_PTR_NOT_NULL(call_marie->log->reporting.reports[0]->info.local_addr.ip); - - // but not this one since it is updated at the end of call - CU_ASSERT_PTR_NULL(call_marie->log->reporting.reports[0]->dialog_id); + // this field should be already filled + CU_ASSERT_PTR_NOT_NULL(call_marie->log->reporting.reports[0]->info.local_addr.ip); + // but not this one since it is updated at the end of call + CU_ASSERT_PTR_NULL(call_marie->log->reporting.reports[0]->dialog_id); + } linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } @@ -189,13 +203,13 @@ static void quality_reporting_not_sent_if_low_bandwidth() { marie_params=linphone_core_create_default_call_parameters(marie->lc); linphone_call_params_enable_low_bandwidth(marie_params,TRUE); - CU_ASSERT_TRUE(call_with_params(marie,pauline,marie_params,NULL)); - - linphone_core_terminate_all_calls(marie->lc); - - CU_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishProgress,0); - CU_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,0); + if (create_call_for_quality_reporting_tests(marie, pauline, NULL, NULL, marie_params, NULL)) { + linphone_core_terminate_all_calls(marie->lc); + CU_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishProgress,0); + CU_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,0); + } + linphone_call_params_destroy(marie_params); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } @@ -212,15 +226,15 @@ static void quality_reporting_invalid_report() { LinphoneCall* call_marie = NULL; LinphoneCall* call_pauline = NULL; - create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline); - linphone_reporting_set_on_report_send(call_marie, on_report_send_remove_fields); + if (create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline, NULL, NULL)) { + linphone_reporting_set_on_report_send(call_marie, on_report_send_remove_fields); - linphone_core_terminate_all_calls(marie->lc); - - CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishProgress,1)); - CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishError,1,3000)); - CU_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,0); + linphone_core_terminate_all_calls(marie->lc); + CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishProgress,1)); + CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishError,1,3000)); + CU_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,0); + } linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } @@ -231,24 +245,24 @@ static void quality_reporting_at_call_termination() { LinphoneCall* call_marie = NULL; LinphoneCall* call_pauline = NULL; - create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline); - linphone_reporting_set_on_report_send(call_marie, on_report_send_with_rtcp_xr_remote); + if (create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline, NULL, NULL)) { + linphone_reporting_set_on_report_send(call_marie, on_report_send_with_rtcp_xr_remote); - linphone_core_terminate_all_calls(marie->lc); + linphone_core_terminate_all_calls(marie->lc); - // now dialog id should be filled - CU_ASSERT_PTR_NOT_NULL(call_marie->log->reporting.reports[0]->dialog_id); + // now dialog id should be filled + CU_ASSERT_PTR_NOT_NULL(call_marie->log->reporting.reports[0]->dialog_id); - CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallReleased,1, 10000)); - CU_ASSERT_TRUE(wait_for_until(pauline->lc,NULL,&pauline->stat.number_of_LinphoneCallReleased,1, 10000)); + CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallReleased,1, 10000)); + CU_ASSERT_TRUE(wait_for_until(pauline->lc,NULL,&pauline->stat.number_of_LinphoneCallReleased,1, 10000)); - CU_ASSERT_PTR_NULL(linphone_core_get_current_call(marie->lc)); - CU_ASSERT_PTR_NULL(linphone_core_get_current_call(pauline->lc)); - - // PUBLISH submission to the collector should be ok - CU_ASSERT_TRUE(wait_for(marie->lc,NULL,&marie->stat.number_of_LinphonePublishProgress,1)); - CU_ASSERT_TRUE(wait_for(marie->lc,NULL,&marie->stat.number_of_LinphonePublishOk,1)); + CU_ASSERT_PTR_NULL(linphone_core_get_current_call(marie->lc)); + CU_ASSERT_PTR_NULL(linphone_core_get_current_call(pauline->lc)); + // PUBLISH submission to the collector should be ok + CU_ASSERT_TRUE(wait_for(marie->lc,NULL,&marie->stat.number_of_LinphonePublishProgress,1)); + CU_ASSERT_TRUE(wait_for(marie->lc,NULL,&marie->stat.number_of_LinphonePublishOk,1)); + } linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } @@ -259,17 +273,17 @@ static void quality_reporting_interval_report() { LinphoneCall* call_marie = NULL; LinphoneCall* call_pauline = NULL; - create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline); - linphone_reporting_set_on_report_send(call_marie, on_report_send_mandatory); - linphone_proxy_config_set_quality_reporting_interval(call_marie->dest_proxy, 3); + if (create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline, NULL, NULL)) { + linphone_reporting_set_on_report_send(call_marie, on_report_send_mandatory); + linphone_proxy_config_set_quality_reporting_interval(call_marie->dest_proxy, 3); - CU_ASSERT_PTR_NOT_NULL(linphone_core_get_current_call(marie->lc)); - CU_ASSERT_PTR_NOT_NULL(linphone_core_get_current_call(pauline->lc)); - - // PUBLISH submission to the collector should be ok - CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishProgress,3,25000)); - CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishOk,3,25000)); + CU_ASSERT_PTR_NOT_NULL(linphone_core_get_current_call(marie->lc)); + CU_ASSERT_PTR_NOT_NULL(linphone_core_get_current_call(pauline->lc)); + // PUBLISH submission to the collector should be ok + CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishProgress,3,25000)); + CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishOk,3,25000)); + } linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } @@ -278,6 +292,7 @@ static void quality_reporting_session_report_if_video_stopped() { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc_rtcp_xr"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); LinphoneCall* call_pauline = NULL; + LinphoneCall* call_marie = NULL; LinphoneCallParams* pauline_params; LinphoneCallParams* marie_params; @@ -289,29 +304,32 @@ static void quality_reporting_session_report_if_video_stopped() { linphone_call_params_enable_video(marie_params,TRUE); pauline_params=linphone_core_create_default_call_parameters(pauline->lc); linphone_call_params_enable_video(pauline_params,TRUE); - CU_ASSERT_TRUE(call_with_params(pauline,marie,pauline_params,marie_params)); - call_pauline=linphone_core_get_current_call(pauline->lc); - linphone_reporting_set_on_report_send(linphone_core_get_current_call(marie->lc), on_report_send_with_rtcp_xr_local); - CU_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishProgress,0); - CU_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,0); + if (create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline, marie_params, pauline_params)) { + linphone_reporting_set_on_report_send(call_marie, on_report_send_with_rtcp_xr_local); - CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,NULL,0,3000)); - CU_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(call_pauline))); + CU_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishProgress,0); + CU_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,0); - /*remove video*/ - linphone_call_params_enable_video(pauline_params,FALSE); - linphone_core_update_call(pauline->lc,call_pauline,pauline_params); + CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,NULL,0,3000)); + CU_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(call_pauline))); - CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishProgress,1,5000)); - CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishOk,1,5000)); + /*remove video*/ + linphone_call_params_enable_video(pauline_params,FALSE); + linphone_core_update_call(pauline->lc,call_pauline,pauline_params); - CU_ASSERT_FALSE(linphone_call_params_video_enabled(linphone_call_get_current_params(call_pauline))); + CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishProgress,1,5000)); + CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishOk,1,5000)); - linphone_core_terminate_all_calls(marie->lc); + CU_ASSERT_FALSE(linphone_call_params_video_enabled(linphone_call_get_current_params(call_pauline))); - CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishProgress,2,5000)); - CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishOk,2,5000)); + linphone_core_terminate_all_calls(marie->lc); + + CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishProgress,2,5000)); + CU_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishOk,2,5000)); + } + linphone_call_params_destroy(marie_params); + linphone_call_params_destroy(pauline_params); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); diff --git a/tester/rcfiles/marie_h264_rc b/tester/rcfiles/marie_h264_rc new file mode 100644 index 000000000..f2ab26190 --- /dev/null +++ b/tester/rcfiles/marie_h264_rc @@ -0,0 +1,55 @@ +[sip] +sip_port=-1 +sip_tcp_port=-1 +sip_tls_port=-1 +default_proxy=0 +ping_with_options=0 +register_only_when_network_is_up=0 +composing_idle_timeout=1 + +[auth_info_0] +username=marie +userid=marie +passwd=secret +realm=sip.example.org + + +[proxy_0] +reg_proxy=sip.example.org;transport=tcp +reg_route=sip.example.org;transport=tcp;lr +reg_identity=sip:marie@sip.example.org +reg_expires=3600 +reg_sendregister=1 +publish=0 +dial_escape_plus=0 +quality_reporting_collector=sip:collector@sip.example.org +quality_reporting_enabled=1 + +[friend_0] +url="Paupoche" +pol=accept +subscribe=0 + + +[rtp] +audio_rtp_port=8070 +video_rtp_port=9072 + +[video] +display=1 +capture=1 +show_local=0 +size=vga +enabled=0 +self_view=0 +automatically_initiate=0 +automatically_accept=0 +device=StaticImage: Static picture + +[sound] +echocancellation=0 #to not overload cpu in case of VG + +[video_codec_0] +mime=H264 +rate=90000 +enabled=1 diff --git a/tester/rcfiles/pauline_h264_rc b/tester/rcfiles/pauline_h264_rc new file mode 100644 index 000000000..d11c7d071 --- /dev/null +++ b/tester/rcfiles/pauline_h264_rc @@ -0,0 +1,52 @@ +[sip] +sip_port=-1 +sip_tcp_port=-1 +sip_tls_port=-1 +default_proxy=0 +ping_with_options=0 +register_only_when_network_is_up=0 +composing_idle_timeout=1 + +[auth_info_0] +username=pauline +userid=pauline +passwd=secret +realm=sip.example.org + + +[proxy_0] +reg_proxy=sip2.linphone.org;transport=tls +reg_route=sip2.linphone.org;transport=tls +reg_identity=sip:pauline@sip.example.org +reg_expires=3600 +reg_sendregister=1 +publish=0 +dial_escape_plus=0 + +#[friend_0] +#url="Mariette" +#pol=accept +#subscribe=0 + +[rtp] +audio_rtp_port=8090 +video_rtp_port=9092 + +[video] +display=0 +capture=1 +show_local=0 +size=vga +enabled=0 +self_view=0 +automatically_initiate=0 +automatically_accept=0 +device=StaticImage: Static picture + +[sound] +echocancellation=0 #to not overload cpu in case of VG + +[video_codec_0] +mime=H264 +rate=90000 +enabled=1 diff --git a/tester/rcfiles/remote_zero_length_params_rc b/tester/rcfiles/remote_zero_length_params_rc new file mode 100644 index 000000000..915722787 --- /dev/null +++ b/tester/rcfiles/remote_zero_length_params_rc @@ -0,0 +1,7 @@ + + +
    + + test +
    +
    diff --git a/tester/rcfiles/zero_length_params_rc b/tester/rcfiles/zero_length_params_rc new file mode 100644 index 000000000..108749a5d --- /dev/null +++ b/tester/rcfiles/zero_length_params_rc @@ -0,0 +1,3 @@ +[test] +zero_len= +non_zero_len=test diff --git a/tester/register_tester.c b/tester/register_tester.c index 612e40a0b..d47ffa2df 100644 --- a/tester/register_tester.c +++ b/tester/register_tester.c @@ -22,20 +22,10 @@ #include "private.h" #include "liblinphone_tester.h" -static void auth_info_requested2(LinphoneCore *lc, const char *realm, const char *username, const char *domain) { - stats* counters; - ms_message("Auth info requested for user id [%s] at realm [%s]\n" - ,username - ,realm); - counters = get_stats(lc); - counters->number_of_auth_info_requested++; - -} static void auth_info_requested(LinphoneCore *lc, const char *realm, const char *username, const char *domain) { LinphoneAuthInfo *info; - auth_info_requested2(lc,realm,username,domain); info=linphone_auth_info_new(test_username,NULL,test_password,NULL,realm,domain); /*create authentication structure from identity*/ linphone_core_add_auth_info(lc,info); /*add authentication info to LinphoneCore*/ } @@ -46,7 +36,9 @@ static LinphoneCoreManager* create_lcm_with_auth(unsigned int with_auth) { LinphoneCoreManager* mgr=linphone_core_manager_new(NULL); if (with_auth) { - mgr->lc->vtable.auth_info_requested=auth_info_requested; + LinphoneCoreVTable* vtable = linphone_vtable_new(); + vtable->auth_info_requested=auth_info_requested; + linphone_core_add_listener(mgr->lc,vtable); } /*to allow testing with 127.0.0.1*/ @@ -322,6 +314,7 @@ static void ha1_authenticated_register(){ static void authenticated_register_with_no_initial_credentials(){ LinphoneCoreManager *mgr; + LinphoneCoreVTable* vtable = linphone_vtable_new(); stats* counters; char route[256]; @@ -329,7 +322,8 @@ static void authenticated_register_with_no_initial_credentials(){ mgr = linphone_core_manager_new(NULL); - mgr->lc->vtable.auth_info_requested=auth_info_requested; + vtable->auth_info_requested=auth_info_requested; + linphone_core_add_listener(mgr->lc,vtable); counters= get_stats(mgr->lc); counters->number_of_auth_info_requested=0; @@ -387,8 +381,6 @@ static void authenticated_register_with_wrong_credentials_with_params_base(const sprintf(route,"sip:%s",test_route); - mgr->lc->vtable.auth_info_requested=auth_info_requested2; - sal_set_refresher_retry_after(mgr->lc->sal,500); if (user_agent) { linphone_core_set_user_agent(mgr->lc,user_agent,NULL); @@ -467,9 +459,12 @@ static void network_state_change(){ counters = get_stats(lc); register_ok=counters->number_of_LinphoneRegistrationOk; linphone_core_set_network_reachable(lc,FALSE); + CU_ASSERT_TRUE(wait_for(lc,lc,&counters->number_of_NetworkReachableFalse,1)); CU_ASSERT_TRUE(wait_for(lc,lc,&counters->number_of_LinphoneRegistrationNone,register_ok)); linphone_core_set_network_reachable(lc,TRUE); + CU_ASSERT_TRUE(wait_for(lc,lc,&counters->number_of_NetworkReachableTrue,1)); wait_for(lc,lc,&counters->number_of_LinphoneRegistrationOk,2*register_ok); + linphone_core_manager_destroy(mgr); } static int get_number_of_udp_proxy(const LinphoneCore* lc) { diff --git a/tester/setup_tester.c b/tester/setup_tester.c index 546042714..eaa9b6a97 100644 --- a/tester/setup_tester.c +++ b/tester/setup_tester.c @@ -23,6 +23,12 @@ #include "lpconfig.h" #include "private.h" +static void linphone_version_test(void){ + const char *version=linphone_core_get_version(); + /*make sure the git version is always included in the version number*/ + CU_ASSERT_TRUE(strstr(version,"unknown")==NULL); +} + static void core_init_test(void) { LinphoneCoreVTable v_table; LinphoneCore* lc; @@ -102,8 +108,62 @@ static void linphone_lpconfig_from_buffer(){ conf = lp_config_new_from_buffer(buffer_linebreaks); CU_ASSERT_STRING_EQUAL(lp_config_get_string(conf,"buffer_linebreaks","test",""),"ok"); lp_config_destroy(conf); +} + +static void linphone_lpconfig_from_buffer_zerolen_value(){ + /* parameters that have no value should return NULL, not "". */ + static const char* zerolen = "[test]\nzero_len=\nnon_zero_len=test"; + LpConfig* conf; + + conf = lp_config_new_from_buffer(zerolen); + + CU_ASSERT_STRING_EQUAL(lp_config_get_string(conf,"test","zero_len","LOL"),"LOL"); + CU_ASSERT_STRING_EQUAL(lp_config_get_string(conf,"test","non_zero_len",""),"test"); + + lp_config_set_string(conf, "test", "non_zero_len", ""); /* should remove "non_zero_len" */ + CU_ASSERT_STRING_EQUAL(lp_config_get_string(conf,"test","non_zero_len","LOL"), "LOL"); + + lp_config_destroy(conf); +} + +static void linphone_lpconfig_from_file_zerolen_value(){ + /* parameters that have no value should return NULL, not "". */ + static const char* zero_rc_file = "zero_length_params_rc"; + char* rc_path = ms_strdup_printf("%s/rcfiles/%s", liblinphone_tester_file_prefix, zero_rc_file); + LpConfig* conf; + + conf = lp_config_new(rc_path); + + CU_ASSERT_STRING_EQUAL(lp_config_get_string(conf,"test","zero_len","LOL"),"LOL"); + CU_ASSERT_STRING_EQUAL(lp_config_get_string(conf,"test","non_zero_len",""),"test"); + + lp_config_set_string(conf, "test", "non_zero_len", ""); /* should remove "non_zero_len" */ + CU_ASSERT_STRING_EQUAL(lp_config_get_string(conf,"test","non_zero_len","LOL"), "LOL"); + + lp_config_destroy(conf); +} + +static void linphone_lpconfig_from_xml_zerolen_value(){ + static const char* zero_xml_file = "remote_zero_length_params_rc"; + char* xml_path = ms_strdup_printf("%s/rcfiles/%s", liblinphone_tester_file_prefix, zero_xml_file); + LpConfig* conf; + + LinphoneCoreManager* mgr = linphone_core_manager_new2("empty_rc",FALSE); + + CU_ASSERT_EQUAL(linphone_remote_provisioning_load_file(mgr->lc, xml_path), 0); + + conf = mgr->lc->config; + + CU_ASSERT_STRING_EQUAL(lp_config_get_string(conf,"test","zero_len","LOL"),"LOL"); + CU_ASSERT_STRING_EQUAL(lp_config_get_string(conf,"test","non_zero_len",""),"test"); + + lp_config_set_string(conf, "test", "non_zero_len", ""); /* should remove "non_zero_len" */ + CU_ASSERT_STRING_EQUAL(lp_config_get_string(conf,"test","non_zero_len","LOL"), "LOL"); + + linphone_core_manager_destroy(mgr); } + void linphone_proxy_config_address_equal_test() { LinphoneAddress *a = linphone_address_new("sip:toto@titi"); LinphoneAddress *b = linphone_address_new("sips:toto@titi"); @@ -166,14 +226,29 @@ void linphone_proxy_config_is_server_config_changed_test() { linphone_proxy_config_destroy(proxy_config); } +static void chat_root_test(void) { + LinphoneCoreVTable v_table; + LinphoneCore* lc; + memset (&v_table,0,sizeof(v_table)); + lc = linphone_core_new(&v_table,NULL,NULL,NULL); + CU_ASSERT_PTR_NOT_NULL_FATAL(lc); + linphone_core_create_chat_room(lc,"sip:toto@titi.com"); + linphone_core_destroy(lc); +} + test_t setup_tests[] = { + { "Version check", linphone_version_test }, { "Linphone Address", linphone_address_test }, { "Linphone proxy config address equal (internal api)", linphone_proxy_config_address_equal_test}, { "Linphone proxy config server address change (internal api)", linphone_proxy_config_is_server_config_changed_test}, { "Linphone core init/uninit", core_init_test }, { "Linphone random transport port",core_sip_transport_test}, { "Linphone interpret url", linphone_interpret_url_test }, - { "LPConfig from buffer", linphone_lpconfig_from_buffer } + { "LPConfig from buffer", linphone_lpconfig_from_buffer }, + { "LPConfig zero_len value from buffer", linphone_lpconfig_from_buffer_zerolen_value }, + { "LPConfig zero_len value from file", linphone_lpconfig_from_file_zerolen_value }, + { "LPConfig zero_len value from XML", linphone_lpconfig_from_xml_zerolen_value }, + { "Chat room", chat_root_test } }; test_suite_t setup_test_suite = { diff --git a/tester/tester.c b/tester/tester.c index 475d2c90f..76a909606 100644 --- a/tester/tester.c +++ b/tester/tester.c @@ -1,4 +1,4 @@ -/* + /* tester - liblinphone test suite Copyright (C) 2013 Belledonne Communications SARL @@ -50,10 +50,22 @@ const char *liblinphone_tester_file_prefix="."; #endif /* TODO: have the same "static" for QNX and windows as above? */ +#ifdef ANDROID +const char *liblinphone_tester_writable_dir_prefix = "/data/data/org.linphone.tester/cache"; +#else const char *liblinphone_tester_writable_dir_prefix = "."; +#endif const char *userhostsfile = "tester_hosts"; - +static void network_reachable(LinphoneCore *lc, bool_t reachable) { + stats* counters; + ms_message("Network reachable [%s]",reachable?"TRUE":"FALSE"); + counters = get_stats(lc); + if (reachable) + counters->number_of_NetworkReachableTrue++; + else + counters->number_of_NetworkReachableFalse++; +} void liblinphone_tester_clock_start(MSTimeSpec *start){ ms_get_cur_time(start); } @@ -156,7 +168,7 @@ bool_t wait_for_list(MSList* lcs,int* counter,int value,int timeout_ms) { for (iterator=lcs;iterator!=NULL;iterator=iterator->next) { linphone_core_iterate((LinphoneCore*)(iterator->data)); } - ms_usleep(100000); + ms_usleep(20000); } if(counter && *counterv_table.call_state_changed=call_state_changed; mgr->v_table.text_received=text_message_received; mgr->v_table.message_received=message_received; - mgr->v_table.file_transfer_received=file_transfer_received; + mgr->v_table.file_transfer_recv=file_transfer_received; mgr->v_table.file_transfer_send=file_transfer_send; mgr->v_table.file_transfer_progress_indication=file_transfer_progress_indication; mgr->v_table.is_composing_received=is_composing_received; @@ -212,6 +224,7 @@ LinphoneCoreManager* linphone_core_manager_new2(const char* rc_file, int check_f mgr->v_table.publish_state_changed=linphone_publish_state_changed; mgr->v_table.configuring_status=linphone_configuration_status; mgr->v_table.call_encryption_changed=linphone_call_encryption_changed; + mgr->v_table.network_reachable=network_reachable; reset_counters(&mgr->stat); if (rc_file) rc_path = ms_strdup_printf("rcfiles/%s", rc_file); @@ -222,6 +235,13 @@ LinphoneCoreManager* linphone_core_manager_new2(const char* rc_file, int check_f else proxy_count=0; +#if TARGET_OS_IPHONE + linphone_core_set_playback_device( mgr->lc, "AU: Audio Unit Tester"); + linphone_core_set_capture_device( mgr->lc, "AU: Audio Unit Tester"); + linphone_core_set_ringer_device( mgr->lc, "AQ: Audio Queue Device"); + linphone_core_set_ringback(mgr->lc, NULL); +#endif + if (proxy_count) wait_for_until(mgr->lc,NULL,&mgr->stat.number_of_LinphoneRegistrationOk,proxy_count,5000*proxy_count); CU_ASSERT_EQUAL(mgr->stat.number_of_LinphoneRegistrationOk,proxy_count); @@ -250,6 +270,7 @@ void linphone_core_manager_stop(LinphoneCoreManager *mgr){ void linphone_core_manager_destroy(LinphoneCoreManager* mgr) { if (mgr->lc) linphone_core_destroy(mgr->lc); if (mgr->identity) linphone_address_destroy(mgr->identity); + if (mgr->stat.last_received_chat_message) linphone_chat_message_unref(mgr->stat.last_received_chat_message); ms_free(mgr); } @@ -294,7 +315,7 @@ int liblinphone_tester_test_suite_index(const char *suite_name) { void liblinphone_tester_list_suites() { int j; for(j=0;j. +*/ + + +#include +#include +#include +#include "CUnit/Basic.h" +#include "linphonecore.h" +#include "lpconfig.h" +#include "private.h" +#include "liblinphone_tester.h" + +/* Retrieve the public IP from a given hostname */ +static const char* get_ip_from_hostname(const char * tunnel_hostname){ + struct addrinfo hints; + struct addrinfo *res = NULL, *it = NULL; + struct sockaddr_in *add; + char * output = NULL; + int err; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + if ((err = getaddrinfo(tunnel_hostname, NULL, &hints, &res))){ + ms_error("error while retrieving IP from %s: %s", tunnel_hostname, gai_strerror(err)); + return NULL; + } + + for (it=res; it!=NULL; it=it->ai_next){ + add = (struct sockaddr_in *) it->ai_addr; + output = inet_ntoa( add->sin_addr ); + } + freeaddrinfo(res); + return output; +} +static char* get_public_contact_ip(LinphoneCore* lc) { + long contact_host_ip_len; + char contact_host_ip[255]; + char * contact = linphone_proxy_config_get_contact(linphone_core_get_default_proxy_config(lc)); + CU_ASSERT_PTR_NOT_NULL(contact); + contact_host_ip_len = strchr(contact, ':')-contact; + strncpy(contact_host_ip, contact, contact_host_ip_len); + contact_host_ip[contact_host_ip_len]='\0'; + ms_free(contact); + return ms_strdup(contact_host_ip); +} +static void call_with_transport_base(bool_t use_tunnel, bool_t with_sip, LinphoneMediaEncryption encryption) { + if (linphone_core_tunnel_available()){ + char *tmp_char; + LinphoneCoreManager *pauline = linphone_core_manager_new( "pauline_rc"); + LinphoneCoreManager *marie = linphone_core_manager_new( "marie_rc"); + LinphoneCall *pauline_call; + LinphoneProxyConfig *proxy = linphone_core_get_default_proxy_config(pauline->lc); + LinphoneAddress *server_addr = linphone_address_new(linphone_proxy_config_get_server_addr(proxy)); + LinphoneAddress *route = linphone_address_new(linphone_proxy_config_get_route(proxy)); + const char * tunnel_ip = get_ip_from_hostname("tunnel.linphone.org"); + char *public_ip; + + CU_ASSERT_TRUE(wait_for(pauline->lc,NULL,&pauline->stat.number_of_LinphoneRegistrationOk,1)); + public_ip = get_public_contact_ip(pauline->lc); + CU_ASSERT_STRING_NOT_EQUAL(public_ip, tunnel_ip); + + linphone_core_set_media_encryption(pauline->lc, encryption); + + if (use_tunnel){ + LinphoneTunnel *tunnel = linphone_core_get_tunnel(pauline->lc); + LinphoneTunnelConfig *config = linphone_tunnel_config_new(); + + /*tunnel works only in UDP mode*/ + linphone_proxy_config_edit(proxy); + linphone_address_set_transport(server_addr, LinphoneTransportUdp); + linphone_address_set_transport(route, LinphoneTransportUdp); + tmp_char = linphone_address_as_string(server_addr); + linphone_proxy_config_set_server_addr(proxy, tmp_char); + ms_free(tmp_char); + tmp_char = linphone_address_as_string(route); + linphone_proxy_config_set_route(proxy, tmp_char); + ms_free(tmp_char); + linphone_tunnel_set_mode(tunnel, LinphoneTunnelModeEnable); + if(with_sip) linphone_tunnel_enable_sip(tunnel, with_sip); + linphone_tunnel_config_set_host(config, "tunnel.linphone.org"); + linphone_tunnel_config_set_port(config, 443); + linphone_tunnel_add_server(tunnel, config); + linphone_proxy_config_done(proxy); + + /*enabling the tunnel cause another REGISTER to be made*/ + CU_ASSERT_TRUE(wait_for(pauline->lc,NULL,&pauline->stat.number_of_LinphoneRegistrationOk,2)); + + /* Ensure that we did use the tunnel. If so, we should see contact changed from: + Contact: ;.[...] + To: + Contact: ;[....] (91.121.209.194 must be tunnel.liphone.org) + */ + ms_free(public_ip); + public_ip = get_public_contact_ip(pauline->lc); + CU_ASSERT_STRING_EQUAL(public_ip, tunnel_ip); + } + + CU_ASSERT_TRUE(call(pauline,marie)); + pauline_call=linphone_core_get_current_call(pauline->lc); + CU_ASSERT_PTR_NOT_NULL(pauline_call); + if (pauline_call!=NULL){ + CU_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(pauline_call)), + encryption); + } + end_call(pauline,marie); + + ms_free(public_ip); + linphone_address_destroy(server_addr); + linphone_address_destroy(route); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(marie); + }else{ + ms_warning("Could not test %s because tunnel functionality is not available",__FUNCTION__); + } +} + +static void call_with_tunnel(void) { + call_with_transport_base(TRUE, TRUE, LinphoneMediaEncryptionNone); +} + +static void call_with_tunnel_srtp(void) { + call_with_transport_base(TRUE, TRUE, LinphoneMediaEncryptionSRTP); +} + +static void call_with_tunnel_without_sip(void) { + call_with_transport_base(TRUE, FALSE, LinphoneMediaEncryptionNone); +} + +test_t transport_tests[] = { + { "Tunnel only", call_with_tunnel }, + { "Tunnel with SRTP", call_with_tunnel_srtp }, + { "Tunnel without SIP", call_with_tunnel_without_sip } +}; + +test_suite_t transport_test_suite = { + "Transport", + NULL, + NULL, + sizeof(transport_tests) / sizeof(transport_tests[0]), + transport_tests +}; diff --git a/tester/upnp_tester.c b/tester/upnp_tester.c index 04b5b865b..656c9c3eb 100644 --- a/tester/upnp_tester.c +++ b/tester/upnp_tester.c @@ -43,9 +43,10 @@ static void upnp_check_state(void) { static void upnp_check_ipaddress(void) { int tmp = 0; + const char *addr; LinphoneCoreManager* lc_upnp = linphone_core_manager_new2( "upnp_rc", FALSE); wait_for(lc_upnp->lc,lc_upnp->lc,&tmp,1); - const char *addr = linphone_core_get_upnp_external_ipaddress(lc_upnp->lc); + addr = linphone_core_get_upnp_external_ipaddress(lc_upnp->lc); CU_ASSERT_TRUE(addr != NULL && strlen(addr)>=7); linphone_core_manager_destroy(lc_upnp); } diff --git a/tools/Makefile.am b/tools/Makefile.am index d993aa591..0515faae2 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -2,17 +2,18 @@ AM_CPPFLAGS=\ -I$(top_srcdir) \ - -I$(top_srcdir)/coreapi + -I$(top_srcdir)/coreapi COMMON_CFLAGS=\ -DIN_LINPHONE \ $(ORTP_CFLAGS) \ $(MEDIASTREAMER_CFLAGS) \ $(STRICT_OPTIONS) \ - $(LIBXML2_CFLAGS) + $(STRICT_OPTIONS_CC) \ + $(LIBXML2_CFLAGS) #-fpermissive to workaround a g++ bug on macos 32bit SDK. -AM_CXXFLAGS=$(LIBXML2_CFLAGS) -fpermissive $(STRICT_OPTIONS) +AM_CXXFLAGS=$(LIBXML2_CFLAGS) -fpermissive $(STRICT_OPTIONS) $(STRICT_OPTIONS_CXX) EXTRA_DIST=xml2lpc_jni.cc lpc2xml_jni.cc diff --git a/tools/genapixml.py b/tools/genapixml.py new file mode 100755 index 000000000..4f834fb0c --- /dev/null +++ b/tools/genapixml.py @@ -0,0 +1,743 @@ +#!/usr/bin/python + +# Copyright (C) 2014 Belledonne Communications SARL +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +import argparse +import os +import string +import sys +import xml.etree.ElementTree as ET +import xml.dom.minidom as minidom + + +class CObject: + def __init__(self, name): + self.name = name.strip() + self.briefDescription = '' + self.detailedDescription = None + self.deprecated = False + + +class CEnumValue(CObject): + pass + + +class CEnum(CObject): + def __init__(self, name): + CObject.__init__(self, name) + self.values = [] + self.associatedTypedef = None + + def addValue(self, value): + self.values.append(value) + + +class CStructMember(CObject): + def __init__(self, name, t): + CObject.__init__(self, name) + self.ctype = t.strip() + + +class CStruct(CObject): + def __init__(self, name): + CObject.__init__(self, name) + self.members = [] + self.associatedTypedef = None + + def addMember(self, member): + self.members.append(member) + + +class CTypedef(CObject): + def __init__(self, name, definition): + CObject.__init__(self, name) + self.definition = definition.strip() + + +class CArgument(CObject): + def __init__(self, t, name = '', enums = [], structs = []): + CObject.__init__(self, name) + self.description = None + self.containedType = None + keywords = [ 'const', 'struct', 'enum', 'signed', 'unsigned', 'short', 'long', '*' ] + fullySplittedType = [] + splittedType = t.strip().split(' ') + for s in splittedType: + if s.startswith('*'): + fullySplittedType.append('*') + if len(s) > 1: + fullySplittedType.append(s[1:]) + elif s.endswith('*'): + fullySplittedType.append(s[:-1]) + fullySplittedType.append('*') + else: + fullySplittedType.append(s) + isStruct = False + isEnum = False + self.ctype = 'int' # Default to int so that the result is correct eg. for 'unsigned short' + for s in fullySplittedType: + if not s in keywords: + self.ctype = s + if s == 'struct': + isStruct = True + if s == 'enum': + isEnum = True + if isStruct: + for st in structs: + if st.associatedTypedef is not None: + self.ctype = st.associatedTypedef.name + elif isEnum: + for e in enums: + if e.associatedTypedef is not None: + self.ctype = e.associatedTypedef.name + if self.ctype == 'int' and 'int' not in fullySplittedType: + if fullySplittedType[-1] == '*': + fullySplittedType.insert(-1, 'int') + else: + fullySplittedType.append('int') + self.completeType = ' '.join(fullySplittedType) + + def __str__(self): + return self.completeType + " " + self.name + + +class CArgumentsList: + def __init__(self): + self.arguments = [] + + def addArgument(self, arg): + self.arguments.append(arg) + + def __len__(self): + return len(self.arguments) + + def __getitem__(self, key): + return self.arguments[key] + + def __str__(self): + argstr = [] + for arg in self.arguments: + argstr.append(str(arg)) + return ', '.join(argstr) + + +class CFunction(CObject): + def __init__(self, name, returnarg, argslist): + CObject.__init__(self, name) + self.returnArgument = returnarg + self.arguments = argslist + self.location = None + + +class CEvent(CFunction): + pass + + +class CProperty: + def __init__(self, name): + self.name = name + self.getter = None + self.setter = None + + +class CClass(CObject): + def __init__(self, st): + CObject.__init__(self, st.associatedTypedef.name) + if st.deprecated or st.associatedTypedef.deprecated: + self.deprecated = True + if len(st.associatedTypedef.briefDescription) > 0: + self.briefDescription = st.associatedTypedef.briefDescription + elif len(st.briefDescription) > 0: + self.briefDescription = st.briefDescription + if st.associatedTypedef.detailedDescription is not None: + self.detailedDescription = st.associatedTypedef.detailedDescription + elif st.detailedDescription is not None: + self.detailedDescription = st.detailedDescription + self.__struct = st + self.events = {} + self.classMethods = {} + self.instanceMethods = {} + self.properties = {} + self.__computeCFunctionPrefix() + + def __computeCFunctionPrefix(self): + self.cFunctionPrefix = '' + first = True + for l in self.name: + if l.isupper() and not first: + self.cFunctionPrefix += '_' + self.cFunctionPrefix += l.lower() + first = False + self.cFunctionPrefix += '_' + + def __addPropertyGetter(self, name, f): + if not name in self.properties: + prop = CProperty(name) + self.properties[name] = prop + self.properties[name].getter = f + + def __addPropertySetter(self, name, f): + if not name in self.properties: + prop = CProperty(name) + self.properties[name] = prop + self.properties[name].setter = f + + def __addClassMethod(self, f): + name = f.name[len(self.cFunctionPrefix):] + if string.find(name, 'get_') == 0 and len(f.arguments) == 0: + self.__addPropertyGetter(name[4:], f) + elif string.find(name, 'is_') == 0 and len(f.arguments) == 0 and f.returnArgument.ctype == 'bool_t': + self.__addPropertyGetter(name[3:], f) + elif string.rfind(name, '_enabled') == (len(name) - 8) and len(f.arguments) == 0 and f.returnArgument.ctype == 'bool_t': + self.__addPropertyGetter(name, f) + elif string.find(name, 'set_') == 0 and len(f.arguments) == 1: + self.__addPropertySetter(name[4:], f) + elif string.find(name, 'enable_') == 0 and len(f.arguments) == 1 and f.arguments[0].ctype == 'bool_t': + self.__addPropertySetter(name[7:] + '_enabled', f) + else: + if not f.name in self.classMethods: + self.classMethods[f.name] = f + + def __addInstanceMethod(self, f): + name = f.name[len(self.cFunctionPrefix):] + if string.find(name, 'get_') == 0 and len(f.arguments) == 1: + self.__addPropertyGetter(name[4:], f) + elif string.find(name, 'is_') == 0 and len(f.arguments) == 1 and f.returnArgument.ctype == 'bool_t': + self.__addPropertyGetter(name[3:], f) + elif string.rfind(name, '_enabled') == (len(name) - 8) and len(f.arguments) == 1 and f.returnArgument.ctype == 'bool_t': + self.__addPropertyGetter(name, f) + elif string.find(name, 'set_') == 0 and len(f.arguments) == 2: + self.__addPropertySetter(name[4:], f) + elif string.find(name, 'enable_') == 0 and len(f.arguments) == 2 and f.arguments[1].ctype == 'bool_t': + self.__addPropertySetter(name[7:] + '_enabled', f) + else: + if not f.name in self.instanceMethods: + self.instanceMethods[f.name] = f + + def addEvent(self, ev): + if not ev.name in self.events: + self.events[ev.name] = ev + + def addMethod(self, f): + if len(f.arguments) > 0 and f.arguments[0].ctype == self.name: + self.__addInstanceMethod(f) + else: + self.__addClassMethod(f) + + +class Project: + def __init__(self): + self.verbose = False + self.prettyPrint = False + self.enums = [] + self.__structs = [] + self.__typedefs = [] + self.__events = [] + self.__functions = [] + self.classes = [] + + def add(self, elem): + if isinstance(elem, CClass): + if self.verbose: + print("Adding class " + elem.name) + self.classes.append(elem) + elif isinstance(elem, CEnum): + if self.verbose: + print("Adding enum " + elem.name) + for ev in elem.values: + print("\t" + ev.name) + self.enums.append(elem) + elif isinstance(elem, CStruct): + if self.verbose: + print("Adding struct " + elem.name) + for sm in elem.members: + print("\t" + sm.ctype + " " + sm.name) + self.__structs.append(elem) + elif isinstance(elem, CTypedef): + if self.verbose: + print("Adding typedef " + elem.name) + print("\t" + elem.definition) + self.__typedefs.append(elem) + elif isinstance(elem, CEvent): + if self.verbose: + print("Adding event " + elem.name) + print("\tReturns: " + elem.returnArgument.ctype) + print("\tArguments: " + str(elem.arguments)) + self.__events.append(elem) + elif isinstance(elem, CFunction): + if self.verbose: + print("Adding function " + elem.name) + print("\tReturns: " + elem.returnArgument.ctype) + print("\tArguments: " + str(elem.arguments)) + self.__functions.append(elem) + + def __cleanDescription(self, descriptionNode): + for para in descriptionNode.findall('./para'): + for n in para.findall('./parameterlist'): + para.remove(n) + for n in para.findall("./simplesect[@kind='return']"): + para.remove(n) + for n in para.findall("./simplesect[@kind='see']"): + t = ''.join(n.itertext()) + n.clear() + n.tag = 'see' + n.text = t + for n in para.findall("./simplesect[@kind='note']"): + n.tag = 'note' + n.attrib = {} + for n in para.findall(".//xrefsect"): + para.remove(n) + for n in para.findall('.//ref'): + n.attrib = {} + for n in para.findall(".//mslist"): + para.remove(n) + if descriptionNode.tag == 'parameterdescription': + descriptionNode.tag = 'description' + if descriptionNode.tag == 'simplesect': + descriptionNode.tag = 'description' + descriptionNode.attrib = {} + return descriptionNode + + def __discoverClasses(self): + for td in self.__typedefs: + if string.find(td.definition, 'enum ') == 0: + for e in self.enums: + if (e.associatedTypedef is None) and td.definition[5:] == e.name: + e.associatedTypedef = td + break + elif string.find(td.definition, 'struct ') == 0: + structFound = False + for st in self.__structs: + if (st.associatedTypedef is None) and td.definition[7:] == st.name: + st.associatedTypedef = td + structFound = True + break + if not structFound: + name = td.definition[7:] + print("Structure with no associated typedef: " + name) + st = CStruct(name) + st.associatedTypedef = td + self.add(st) + for td in self.__typedefs: + if string.find(td.definition, 'struct ') == 0: + for st in self.__structs: + if st.associatedTypedef == td: + self.add(CClass(st)) + break + elif ('Linphone' + td.definition) == td.name: + st = CStruct(td.name) + st.associatedTypedef = td + self.add(st) + self.add(CClass(st)) + # Sort classes by length of name (longest first), so that methods are put in the right class + self.classes.sort(key = lambda c: len(c.name), reverse = True) + for e in self.__events: + for c in self.classes: + if string.find(e.name, c.name) == 0: + c.addEvent(e) + for f in self.__functions: + for c in self.classes: + if c.cFunctionPrefix == f.name[0 : len(c.cFunctionPrefix)]: + c.addMethod(f) + break + + def __parseCEnumValue(self, node): + ev = CEnumValue(node.find('./name').text) + deprecatedNode = node.find(".//xrefsect[xreftitle='Deprecated']") + if deprecatedNode is not None: + ev.deprecated = True + ev.briefDescription = ''.join(node.find('./briefdescription').itertext()).strip() + ev.detailedDescription = self.__cleanDescription(node.find('./detaileddescription')) + return ev + + def __parseCEnumMemberdef(self, node): + e = CEnum(node.find('./name').text) + deprecatedNode = node.find(".//xrefsect[xreftitle='Deprecated']") + if deprecatedNode is not None: + e.deprecated = True + e.briefDescription = ''.join(node.find('./briefdescription').itertext()).strip() + e.detailedDescription = self.__cleanDescription(node.find('./detaileddescription')) + enumvalues = node.findall("enumvalue[@prot='public']") + for enumvalue in enumvalues: + ev = self.__parseCEnumValue(enumvalue) + e.addValue(ev) + return e + + def __findCEnum(self, tree): + memberdefs = tree.findall("./compounddef[@kind='group']/sectiondef[@kind='enum']/memberdef[@kind='enum'][@prot='public']") + for m in memberdefs: + e = self.__parseCEnumMemberdef(m) + self.add(e) + + def __parseCStructMember(self, node, structname): + name = node.find('./name').text + definition = node.find('./definition').text + t = definition[0:string.find(definition, structname + "::" + name)] + sm = CStructMember(name, t) + deprecatedNode = node.find(".//xrefsect[xreftitle='Deprecated']") + if deprecatedNode is not None: + sm.deprecated = True + sm.briefDescription = ''.join(node.find('./briefdescription').itertext()).strip() + sm.detailedDescription = self.__cleanDescription(node.find('./detaileddescription')) + return sm + + def __parseCStructCompounddef(self, node): + s = CStruct(node.find('./compoundname').text) + deprecatedNode = node.find(".//xrefsect[xreftitle='Deprecated']") + if deprecatedNode is not None: + s.deprecated = True + s.briefDescription = ''.join(node.find('./briefdescription').itertext()).strip() + s.detailedDescription = self.__cleanDescription(node.find('./detaileddescription')) + structmembers = node.findall("sectiondef/memberdef[@kind='variable'][@prot='public']") + for structmember in structmembers: + sm = self.__parseCStructMember(structmember, s.name) + s.addMember(sm) + return s + + def __findCStruct(self, tree): + compounddefs = tree.findall("./compounddef[@kind='struct'][@prot='public']") + for c in compounddefs: + s = self.__parseCStructCompounddef(c) + self.add(s) + + def __parseCTypedefMemberdef(self, node): + name = node.find('./name').text + definition = node.find('./definition').text + if string.find(definition, 'typedef ') == 0: + definition = definition[8 :] + if string.rfind(name, 'Cb') == len(name) - 2: + pos = string.find(definition, "(*") + if pos == -1: + return None + returntype = definition[0:pos].strip() + if returntype != "void": + return None + returnarg = CArgument(returntype, enums = self.enums, structs = self.__structs) + definition = definition[pos + 2 :] + pos = string.find(definition, "(") + definition = definition[pos + 1 : -1] + argslist = CArgumentsList() + for argdef in definition.split(', '): + argType = '' + starPos = string.rfind(argdef, '*') + spacePos = string.rfind(argdef, ' ') + if starPos != -1: + argType = argdef[0 : starPos + 1] + argName = argdef[starPos + 1 :] + elif spacePos != -1: + argType = argdef[0 : spacePos] + argName = argdef[spacePos + 1 :] + argslist.addArgument(CArgument(argType, argName, self.enums, self.__structs)) + if len(argslist) > 0: + paramdescs = node.findall("detaileddescription/para/parameterlist[@kind='param']/parameteritem") + if paramdescs: + for arg in argslist.arguments: + for paramdesc in paramdescs: + if arg.name == paramdesc.find('./parameternamelist').find('./parametername').text: + arg.description = self.__cleanDescription(paramdesc.find('./parameterdescription')) + missingDocWarning = '' + for arg in argslist.arguments: + if arg.description == None: + missingDocWarning += "\t'" + arg.name + "' parameter not documented\n"; + if missingDocWarning != '': + print(name + ":\n" + missingDocWarning) + f = CEvent(name, returnarg, argslist) + deprecatedNode = node.find(".//xrefsect[xreftitle='Deprecated']") + if deprecatedNode is not None: + f.deprecated = True + f.briefDescription = ''.join(node.find('./briefdescription').itertext()).strip() + f.detailedDescription = self.__cleanDescription(node.find('./detaileddescription')) + return f + else: + pos = string.rfind(definition, " " + name) + if pos != -1: + definition = definition[0 : pos] + td = CTypedef(name, definition) + deprecatedNode = node.find(".//xrefsect[xreftitle='Deprecated']") + if deprecatedNode is not None: + td.deprecated = True + td.briefDescription = ''.join(node.find('./briefdescription').itertext()).strip() + td.detailedDescription = self.__cleanDescription(node.find('./detaileddescription')) + return td + return None + + def __findCTypedef(self, tree): + memberdefs = tree.findall("./compounddef[@kind='group']/sectiondef[@kind='typedef']/memberdef[@kind='typedef'][@prot='public']") + for m in memberdefs: + td = self.__parseCTypedefMemberdef(m) + self.add(td) + + def __parseCFunctionMemberdef(self, node): + missingDocWarning = '' + name = node.find('./name').text + t = ''.join(node.find('./type').itertext()) + returnarg = CArgument(t, enums = self.enums, structs = self.__structs) + returndesc = node.find("./detaileddescription/para/simplesect[@kind='return']") + if returndesc is not None: + if returnarg.ctype == 'MSList': + n = returndesc.find('.//mslist') + if n is not None: + returnarg.containedType = n.text + returnarg.description = self.__cleanDescription(returndesc) + elif returnarg.completeType != 'void': + missingDocWarning += "\tReturn value is not documented\n" + argslist = CArgumentsList() + argslistNode = node.findall('./param') + for argNode in argslistNode: + argType = ''.join(argNode.find('./type').itertext()) + argName = '' + argNameNode = argNode.find('./declname') + if argNameNode is not None: + argName = ''.join(argNameNode.itertext()) + if argType != 'void': + argslist.addArgument(CArgument(argType, argName, self.enums, self.__structs)) + if len(argslist) > 0: + paramdescs = node.findall("./detaileddescription/para/parameterlist[@kind='param']/parameteritem") + if paramdescs: + for arg in argslist.arguments: + for paramdesc in paramdescs: + if arg.name == paramdesc.find('./parameternamelist').find('./parametername').text: + if arg.ctype == 'MSList': + n = paramdesc.find('.//mslist') + if n is not None: + arg.containedType = n.text + arg.description = self.__cleanDescription(paramdesc.find('./parameterdescription')) + missingDocWarning = '' + for arg in argslist.arguments: + if arg.description == None: + missingDocWarning += "\t'" + arg.name + "' parameter not documented\n"; + f = CFunction(name, returnarg, argslist) + deprecatedNode = node.find(".//xrefsect[xreftitle='Deprecated']") + if deprecatedNode is not None: + f.deprecated = True + f.briefDescription = ''.join(node.find('./briefdescription').itertext()).strip() + f.detailedDescription = self.__cleanDescription(node.find('./detaileddescription')) + if f.briefDescription == '' and ''.join(f.detailedDescription.itertext()).strip() == '': + return None + locationNode = node.find('./location') + if locationNode is not None: + f.location = locationNode.get('file') + if not f.location.endswith('.h'): + missingDocWarning += "\tNot documented in a header file ('" + f.location + "')\n"; + if missingDocWarning != '': + print(name + ":\n" + missingDocWarning) + return f + + def __findCFunction(self, tree): + memberdefs = tree.findall("./compounddef[@kind='group']/sectiondef[@kind='func']/memberdef[@kind='function'][@prot='public'][@static='no']") + for m in memberdefs: + f = self.__parseCFunctionMemberdef(m) + self.add(f) + + def initFromFiles(self, xmlfiles): + trees = [] + for f in xmlfiles: + tree = None + try: + if self.verbose: + print("Parsing XML file: " + f.name) + tree = ET.parse(f) + except ET.ParseError as e: + print(e) + if tree is not None: + trees.append(tree) + for tree in trees: + self.__findCEnum(tree) + for tree in trees: + self.__findCStruct(tree) + for tree in trees: + self.__findCTypedef(tree) + for tree in trees: + self.__findCFunction(tree) + self.__discoverClasses() + + def initFromDir(self, xmldir): + files = [ os.path.join(xmldir, f) for f in os.listdir(xmldir) if (os.path.isfile(os.path.join(xmldir, f)) and f.endswith('.xml')) ] + self.initFromFiles(files) + + def check(self): + for c in self.classes: + for name, p in c.properties.iteritems(): + if p.getter is None and p.setter is not None: + print("Property '" + name + "' of class '" + c.name + "' has a setter but no getter") + + +class Generator: + def __init__(self, outputfile): + self.__outputfile = outputfile + + def __generateEnum(self, cenum, enumsNode): + enumNodeAttributes = { 'name' : cenum.name, 'deprecated' : str(cenum.deprecated).lower() } + if cenum.associatedTypedef is not None: + enumNodeAttributes['name'] = cenum.associatedTypedef.name + enumNode = ET.SubElement(enumsNode, 'enum', enumNodeAttributes) + if cenum.briefDescription != '': + enumBriefDescriptionNode = ET.SubElement(enumNode, 'briefdescription') + enumBriefDescriptionNode.text = cenum.briefDescription + enumNode.append(cenum.detailedDescription) + if len(cenum.values) > 0: + enumValuesNode = ET.SubElement(enumNode, 'values') + for value in cenum.values: + enumValuesNodeAttributes = { 'name' : value.name, 'deprecated' : str(value.deprecated).lower() } + valueNode = ET.SubElement(enumValuesNode, 'value', enumValuesNodeAttributes) + if value.briefDescription != '': + valueBriefDescriptionNode = ET.SubElement(valueNode, 'briefdescription') + valueBriefDescriptionNode.text = value.briefDescription + valueNode.append(value.detailedDescription) + + def __generateFunction(self, parentNode, nodeName, f): + functionAttributes = { 'name' : f.name, 'deprecated' : str(f.deprecated).lower() } + if f.location is not None: + functionAttributes['location'] = f.location + functionNode = ET.SubElement(parentNode, nodeName, functionAttributes) + returnValueAttributes = { 'type' : f.returnArgument.ctype, 'completetype' : f.returnArgument.completeType } + if f.returnArgument.containedType is not None: + returnValueAttributes['containedtype'] = f.returnArgument.containedType + returnValueNode = ET.SubElement(functionNode, 'return', returnValueAttributes) + if f.returnArgument.description is not None: + returnValueNode.append(f.returnArgument.description) + argumentsNode = ET.SubElement(functionNode, 'arguments') + for arg in f.arguments: + argumentNodeAttributes = { 'name' : arg.name, 'type' : arg.ctype, 'completetype' : arg.completeType } + if arg.containedType is not None: + argumentNodeAttributes['containedtype'] = arg.containedType + argumentNode = ET.SubElement(argumentsNode, 'argument', argumentNodeAttributes) + if arg.description is not None: + argumentNode.append(arg.description) + if f.briefDescription != '': + functionBriefDescriptionNode = ET.SubElement(functionNode, 'briefdescription') + functionBriefDescriptionNode.text = f.briefDescription + functionNode.append(f.detailedDescription) + + def __generateClass(self, cclass, classesNode): + # Do not include classes that contain nothing + if len(cclass.events) == 0 and len(cclass.classMethods) == 0 and \ + len(cclass.instanceMethods) == 0 and len(cclass.properties) == 0: + return + # Check the capabilities of the class + has_ref_method = False + has_unref_method = False + has_destroy_method = False + for methodname in cclass.instanceMethods: + methodname_without_prefix = methodname.replace(cclass.cFunctionPrefix, '') + if methodname_without_prefix == 'ref': + has_ref_method = True + elif methodname_without_prefix == 'unref': + has_unref_method = True + elif methodname_without_prefix == 'destroy': + has_destroy_method = True + refcountable = False + destroyable = False + if has_ref_method and has_unref_method: + refcountable = True + if has_destroy_method: + destroyable = True + classNodeAttributes = { + 'name' : cclass.name, + 'cfunctionprefix' : cclass.cFunctionPrefix, + 'deprecated' : str(cclass.deprecated).lower(), + 'refcountable' : str(refcountable).lower(), + 'destroyable' : str(destroyable).lower() + } + # Generate the XML node for the class + classNode = ET.SubElement(classesNode, 'class', classNodeAttributes) + if len(cclass.events) > 0: + eventsNode = ET.SubElement(classNode, 'events') + eventnames = [] + for eventname in cclass.events: + eventnames.append(eventname) + eventnames.sort() + for eventname in eventnames: + self.__generateFunction(eventsNode, 'event', cclass.events[eventname]) + if len(cclass.classMethods) > 0: + classMethodsNode = ET.SubElement(classNode, 'classmethods') + methodnames = [] + for methodname in cclass.classMethods: + methodnames.append(methodname) + methodnames.sort() + for methodname in methodnames: + self.__generateFunction(classMethodsNode, 'classmethod', cclass.classMethods[methodname]) + if len(cclass.instanceMethods) > 0: + instanceMethodsNode = ET.SubElement(classNode, 'instancemethods') + methodnames = [] + for methodname in cclass.instanceMethods: + methodnames.append(methodname) + methodnames.sort() + for methodname in methodnames: + self.__generateFunction(instanceMethodsNode, 'instancemethod', cclass.instanceMethods[methodname]) + if len(cclass.properties) > 0: + propertiesNode = ET.SubElement(classNode, 'properties') + propnames = [] + for propname in cclass.properties: + propnames.append(propname) + propnames.sort() + for propname in propnames: + propertyNodeAttributes = { 'name' : propname } + propertyNode = ET.SubElement(propertiesNode, 'property', propertyNodeAttributes) + if cclass.properties[propname].getter is not None: + self.__generateFunction(propertyNode, 'getter', cclass.properties[propname].getter) + if cclass.properties[propname].setter is not None: + self.__generateFunction(propertyNode, 'setter', cclass.properties[propname].setter) + if cclass.briefDescription != '': + classBriefDescriptionNode = ET.SubElement(classNode, 'briefdescription') + classBriefDescriptionNode.text = cclass.briefDescription + classNode.append(cclass.detailedDescription) + + def generate(self, project): + print("Generating XML document of Linphone API to '" + self.__outputfile.name + "'") + apiNode = ET.Element('api') + project.enums.sort(key = lambda e: e.name) + if len(project.enums) > 0: + enumsNode = ET.SubElement(apiNode, 'enums') + for cenum in project.enums: + self.__generateEnum(cenum, enumsNode) + if len(project.classes) > 0: + classesNode = ET.SubElement(apiNode, 'classes') + project.classes.sort(key = lambda c: c.name) + for cclass in project.classes: + self.__generateClass(cclass, classesNode) + s = '\n' + s += ET.tostring(apiNode, 'utf-8') + if project.prettyPrint: + s = minidom.parseString(s).toprettyxml(indent='\t') + self.__outputfile.write(s) + + + +def main(argv = None): + if argv is None: + argv = sys.argv + argparser = argparse.ArgumentParser(description="Generate XML version of the Linphone API.") + argparser.add_argument('-o', '--outputfile', metavar='outputfile', type=argparse.FileType('w'), help="Output XML file describing the Linphone API.") + argparser.add_argument('--verbose', help="Increase output verbosity", action='store_true') + argparser.add_argument('--pretty', help="XML pretty print", action='store_true') + argparser.add_argument('xmldir', help="XML directory generated by doxygen.") + args = argparser.parse_args() + if args.outputfile == None: + args.outputfile = open('api.xml', 'w') + project = Project() + if args.verbose: + project.verbose = True + if args.pretty: + project.prettyPrint = True + project.initFromDir(args.xmldir) + project.check() + gen = Generator(args.outputfile) + gen.generate(project) + +if __name__ == "__main__": + sys.exit(main()) diff --git a/tools/lpc2xml_test.c b/tools/lpc2xml_test.c index cdad72f97..03ac571cf 100644 --- a/tools/lpc2xml_test.c +++ b/tools/lpc2xml_test.c @@ -47,13 +47,15 @@ void show_usage(int argc, char *argv[]) { } int main(int argc, char *argv[]) { + lpc2xml_context *ctx; + LpConfig *lpc; if(argc != 4) { show_usage(argc, argv); return -1; } - - lpc2xml_context *ctx = lpc2xml_context_new(cb_function, NULL); - LpConfig *lpc = lp_config_new(argv[2]); + + ctx = lpc2xml_context_new(cb_function, NULL); + lpc = lp_config_new(argv[2]); lpc2xml_set_lpc(ctx, lpc); if(strcmp("convert", argv[1]) == 0) { lpc2xml_convert_file(ctx, argv[3]); diff --git a/tools/python/.gitignore b/tools/python/.gitignore new file mode 100644 index 000000000..701f19514 --- /dev/null +++ b/tools/python/.gitignore @@ -0,0 +1,4 @@ +*.pyc +build +linphone.c +.kdev* diff --git a/tools/python/apixml2python.py b/tools/python/apixml2python.py new file mode 100755 index 000000000..73fe2c257 --- /dev/null +++ b/tools/python/apixml2python.py @@ -0,0 +1,116 @@ +#!/usr/bin/python + +# Copyright (C) 2014 Belledonne Communications SARL +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +import argparse +import os +import pystache +import sys +import xml.etree.ElementTree as ET + +sys.path.append(os.path.realpath(__file__)) +from apixml2python.linphone import LinphoneModule + + +blacklisted_classes = [ + 'LinphoneTunnel', + 'LinphoneTunnelConfig' +] +blacklisted_events = [ + 'LinphoneCoreInfoReceivedCb', # missing LinphoneInfoMessage + 'LinphoneCoreNotifyReceivedCb', # missing LinphoneContent + 'LinphoneCoreFileTransferProgressIndicationCb', # missing LinphoneContent + 'LinphoneCoreFileTransferRecvCb', # missing LinphoneContent + 'LinphoneCoreFileTransferSendCb' # missing LinphoneContent +] +blacklisted_functions = [ + 'linphone_call_log_get_local_stats', # missing rtp_stats_t + 'linphone_call_log_get_remote_stats', # missing rtp_stats_t + 'linphone_call_params_get_privacy', # missing LinphonePrivacyMask + 'linphone_call_params_set_privacy', # missing LinphonePrivacyMask + 'linphone_chat_message_get_file_transfer_information', # missing LinphoneContent + 'linphone_chat_message_start_file_download', # to be handwritten because of callback + 'linphone_chat_message_state_to_string', # There is no use to wrap this function + 'linphone_chat_room_create_file_transfer_message', # missing LinphoneContent + 'linphone_core_can_we_add_call', # private function + 'linphone_core_get_audio_port_range', # to be handwritten because of result via arguments + 'linphone_core_get_sip_transports', # missing LCSipTransports + 'linphone_core_get_sip_transports_used', # missing LCSipTransports + 'linphone_core_get_supported_video_sizes', # missing MSVideoSizeDef + 'linphone_core_get_video_policy', # missing LinphoneVideoPolicy + 'linphone_core_get_video_port_range', # to be handwritten because of result via arguments + 'linphone_core_publish', # missing LinphoneContent + 'linphone_core_serialize_logs', # There is no use to wrap this function + 'linphone_core_set_log_file', # There is no use to wrap this function + 'linphone_core_set_log_handler', # Hand-written but put directly in the linphone module + 'linphone_core_set_log_level', # There is no use to wrap this function + 'linphone_core_set_video_policy', # missing LinphoneVideoPolicy + 'linphone_core_set_sip_transports', # missing LCSipTransports + 'linphone_core_subscribe', # missing LinphoneContent + 'linphone_event_notify', # missing LinphoneContent + 'linphone_event_send_publish', # missing LinphoneContent + 'linphone_event_send_subscribe', # missing LinphoneContent + 'linphone_event_update_publish', # missing LinphoneContent + 'linphone_event_update_subscribe', # missing LinphoneContent + 'linphone_proxy_config_get_privacy', # missing LinphonePrivacyMask + 'linphone_proxy_config_normalize_number', # to be handwritten because of result via arguments + 'linphone_proxy_config_set_file_transfer_server', # defined but not implemented in linphone core + 'linphone_proxy_config_set_privacy', # missing LinphonePrivacyMask + 'linphone_tunnel_get_http_proxy', # to be handwritten because of double pointer indirection + 'lp_config_for_each_entry', # to be handwritten because of callback + 'lp_config_for_each_section', # to be handwritten because of callback + 'lp_config_get_range', # to be handwritten because of result via arguments + 'lp_config_load_dict_to_section', # missing LinphoneDictionary + 'lp_config_section_to_dict' # missing LinphoneDictionary +] +hand_written_functions = [ + 'linphone_chat_room_send_message2', + 'linphone_core_get_sound_devices', + 'linphone_core_get_video_devices', + 'linphone_core_new', + 'linphone_core_new_with_config' +] + +def generate(apixmlfile, outputfile): + tree = ET.parse(apixmlfile) + renderer = pystache.Renderer() + m = LinphoneModule(tree, blacklisted_classes, blacklisted_events, blacklisted_functions, hand_written_functions) + os.chdir('apixml2python') + tmpfilename = outputfile.name + '.tmp' + f = open(tmpfilename, 'w') + f.write(renderer.render(m)) + f.close() + f = open(tmpfilename, 'rU') + for line in f: + outputfile.write(line) + f.close() + os.unlink(tmpfilename) + + +def main(argv = None): + if argv is None: + argv = sys.argv + argparser = argparse.ArgumentParser(description="Generate a Python wrapper of the Linphone API.") + argparser.add_argument('-o', '--outputfile', metavar='outputfile', type=argparse.FileType('w'), help="Output C file containing the code of the Python wrapper.") + argparser.add_argument('apixmlfile', help="XML file of the Linphone API generated by genapixml.py.") + args = argparser.parse_args() + if args.outputfile == None: + args.outputfile = open('linphone.c', 'w') + generate(args.apixmlfile, args.outputfile) + +if __name__ == "__main__": + sys.exit(main()) diff --git a/tools/python/apixml2python/__init__.py b/tools/python/apixml2python/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tools/python/apixml2python/handwritten_declarations.mustache b/tools/python/apixml2python/handwritten_declarations.mustache new file mode 100644 index 000000000..d5be0a3c4 --- /dev/null +++ b/tools/python/apixml2python/handwritten_declarations.mustache @@ -0,0 +1,15 @@ +static PyObject * pylinphone_Core_get_sound_devices(PyObject *self, void *closure); +static PyObject * pylinphone_Core_get_video_devices(PyObject *self, void *closure); + +static PyTypeObject pylinphone_VideoSizeType; + +typedef struct { + PyObject_HEAD + MSVideoSize vs; +} pylinphone_VideoSizeObject; + +int PyLinphoneVideoSize_Check(PyObject *p); +MSVideoSize PyLinphoneVideoSize_AsMSVideoSize(PyObject *obj); +PyObject * PyLinphoneVideoSize_FromMSVideoSize(MSVideoSize vs); +time_t PyDateTime_As_time_t(PyObject *obj); +PyObject * PyDateTime_From_time_t(time_t t); diff --git a/tools/python/apixml2python/handwritten_definitions.mustache b/tools/python/apixml2python/handwritten_definitions.mustache new file mode 100644 index 000000000..4ae90a9ac --- /dev/null +++ b/tools/python/apixml2python/handwritten_definitions.mustache @@ -0,0 +1,528 @@ +static void pylinphone_dispatch_messages(void) { +#ifdef WIN32 + MSG msg; + while (PeekMessage(&msg, NULL, 0, 0, 1)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } +#endif +} + +static void pylinphone_log(const char *level, int indent, const char *fmt, va_list args) { + static int current_indent = 1; + PyObject *linphone_module; + PyGILState_STATE gstate; + + gstate = PyGILState_Ensure(); + if (gstate != PyGILState_LOCKED) return; + linphone_module = PyImport_ImportModule("linphone.linphone"); + if (linphone_module != NULL) { + if (PyObject_HasAttrString(linphone_module, "__log_handler")) { + PyObject *log_handler = PyObject_GetAttrString(linphone_module, "__log_handler"); + if (log_handler != NULL) { + if (PyCallable_Check(log_handler)) { + char logstr[4096]; + int i = 0; + if (indent == -1) current_indent--; + if (current_indent < 1) current_indent = 1; + if ((indent >= -1) && (indent <= 1)) { + for (i = 0; i < current_indent; i++) { + logstr[i] = '\t'; + } + } + if (indent == 1) current_indent++; + if (vsnprintf(logstr + i, sizeof(logstr) - i, fmt, args) > 0) { + PyObject *pyargs = Py_BuildValue("ss", level, logstr); + if (PyEval_CallObject(log_handler, pyargs) == NULL) { + PyErr_Print(); + } + Py_DECREF(pyargs); + } + } + Py_DECREF(log_handler); + } + } + Py_DECREF(linphone_module); + } + PyGILState_Release(gstate); +} + +static PYLINPHONE_INLINE void pylinphone_trace(int indent, const char *fmt, ...) { + va_list args; + va_start(args, fmt); + pylinphone_log("debug", indent, fmt, args); + va_end(args); +} + +static const char * pylinphone_ortp_log_level_to_string(OrtpLogLevel lev) { + switch (lev) { + default: + case ORTP_DEBUG: + return "debug"; + case ORTP_MESSAGE: + return "info"; + case ORTP_WARNING: + return "warning"; + case ORTP_ERROR: + return "error"; + case ORTP_FATAL: + return "critical"; + case ORTP_TRACE: + return "debug"; + } +} + +static void pylinphone_module_log_handler(OrtpLogLevel lev, const char *fmt, va_list args) { + PyGILState_STATE gstate; + PyObject *linphone_module; + const char *level; + + gstate = PyGILState_Ensure(); + if (gstate != PyGILState_LOCKED) return; + linphone_module = PyImport_ImportModule("linphone.linphone"); + level = pylinphone_ortp_log_level_to_string(lev); + if (linphone_module != NULL) { + if (PyObject_HasAttrString(linphone_module, "__log_handler")) { + PyObject *log_handler = PyObject_GetAttrString(linphone_module, "__log_handler"); + if (log_handler != NULL) { + if (PyCallable_Check(log_handler)) { + char logstr[4096]; + if (vsnprintf(logstr, sizeof(logstr), fmt, args) > 0) { + PyObject *pyargs = Py_BuildValue("ss", level, logstr); + if (PyEval_CallObject(log_handler, pyargs) == NULL) { + PyErr_Print(); + } + Py_DECREF(pyargs); + } + } + Py_DECREF(log_handler); + } + } + Py_DECREF(linphone_module); + } + PyGILState_Release(gstate); +} + +static void pylinphone_init_logging(void) { + linphone_core_serialize_logs(); + linphone_core_set_log_handler(pylinphone_module_log_handler); + linphone_core_set_log_level(ORTP_MESSAGE|ORTP_WARNING|ORTP_ERROR|ORTP_FATAL); +} + + +static PyObject * pylinphone_module_method_set_log_handler(PyObject *self, PyObject *args) { + PyObject *linphone_module = PyImport_ImportModule("linphone.linphone"); + PyObject *callback; + if (!PyArg_ParseTuple(args, "O", &callback)) { + return NULL; + } + if (!PyCallable_Check(callback) && (callback != Py_None)) { + PyErr_SetString(PyExc_TypeError, "The argument must be a callable or None"); + return NULL; + } + if (linphone_module != NULL) { + PyObject_SetAttrString(linphone_module, "__log_handler", callback); + Py_DECREF(linphone_module); + } + Py_RETURN_NONE; +} + + +static PyObject * pylinphone_Core_get_sound_devices(PyObject *self, void *closure) { + PyObject *_list; + const char **_devices; + LinphoneCore *native_ptr = pylinphone_Core_get_native_ptr(self); + + if (native_ptr == NULL) { + PyErr_SetString(PyExc_TypeError, "Invalid linphone.Core instance"); + return NULL; + } + + pylinphone_trace(1, "[PYLINPHONE] >>> %s(%p [%p])", __FUNCTION__, self, native_ptr); + _devices = linphone_core_get_sound_devices(native_ptr); + pylinphone_dispatch_messages(); + + _list = PyList_New(0); + while (*_devices != NULL) { + PyObject *_item = PyString_FromString(*_devices); + PyList_Append(_list, _item); + _devices++; + } + + pylinphone_trace(-1, "[PYLINPHONE] <<< %s -> %p", __FUNCTION__, _list); + return _list; +} + +static PyObject * pylinphone_Core_get_video_devices(PyObject *self, void *closure) { + PyObject *_list; + const char **_devices; + LinphoneCore *native_ptr = pylinphone_Core_get_native_ptr(self); + + if (native_ptr == NULL) { + PyErr_SetString(PyExc_TypeError, "Invalid linphone.Core instance"); + return NULL; + } + + pylinphone_trace(1, "[PYLINPHONE] >>> %s(%p [%p])", __FUNCTION__, self, native_ptr); + _devices = linphone_core_get_video_devices(native_ptr); + pylinphone_dispatch_messages(); + + _list = PyList_New(0); + while (*_devices != NULL) { + PyObject *_item = PyString_FromString(*_devices); + PyList_Append(_list, _item); + _devices++; + } + + pylinphone_trace(-1, "[PYLINPHONE] <<< %s -> %p", __FUNCTION__, _list); + return _list; +} + +static PyObject * pylinphone_Core_class_method_new(PyObject *cls, PyObject *args) { + LinphoneCore * cresult; + pylinphone_CoreObject *self; + PyObject * pyret; + LinphoneCoreVTable _vtable = { 0 }; + PyObject * _vtable_dict; + const char * _config_path; + const char * _factory_config_path; + + if (!PyArg_ParseTuple(args, "Ozz", &_vtable_dict, &_config_path, &_factory_config_path)) { + return NULL; + } + if (!PyDict_Check(_vtable_dict)) { + PyErr_SetString(PyExc_TypeError, "The first argument must be a dictionary"); + return NULL; + } + + self = (pylinphone_CoreObject *)PyObject_CallObject((PyObject *) &pylinphone_CoreType, NULL); + if (self == NULL) { + return NULL; + } + Py_INCREF(_vtable_dict); + self->vtable_dict = _vtable_dict; +{{#events}} + {{{event_vtable_reference}}} +{{/events}} + + pylinphone_trace(1, "[PYLINPHONE] >>> %s(%p, \"%s\", \"%s\")", __FUNCTION__, _vtable_dict, _config_path, _factory_config_path); + cresult = linphone_core_new(&_vtable, _config_path, _factory_config_path, self); + self->native_ptr = cresult; + + pyret = Py_BuildValue("O", self); + + pylinphone_trace(-1, "[PYLINPHONE] <<< %s -> %p", __FUNCTION__, pyret); + Py_DECREF(self); + return pyret; +} + +static PyObject * pylinphone_Core_class_method_new_with_config(PyObject *cls, PyObject *args) { + LinphoneCore * cresult; + pylinphone_CoreObject *self; + PyObject * pyret; + LinphoneCoreVTable _vtable = { 0 }; + PyObject * _vtable_dict; + PyObject * _config; + LpConfig * _config_native_ptr; + + if (!PyArg_ParseTuple(args, "OO", &_vtable_dict, &_config)) { + return NULL; + } + if (!PyDict_Check(_vtable_dict)) { + PyErr_SetString(PyExc_TypeError, "The first argument must be a dictionary"); + return NULL; + } + + if ((_config_native_ptr = pylinphone_LpConfig_get_native_ptr(_config)) == NULL) { + return NULL; + } + + self = (pylinphone_CoreObject *)PyObject_CallObject((PyObject *) &pylinphone_CoreType, NULL); + if (self == NULL) { + return NULL; + } + Py_INCREF(_vtable_dict); + self->vtable_dict = _vtable_dict; +{{#events}} + {{{event_vtable_reference}}} +{{/events}} + + pylinphone_trace(1, "[PYLINPHONE] >>> %s(%p [%p])", __FUNCTION__, _config, _config_native_ptr); + cresult = linphone_core_new_with_config(&_vtable, _config_native_ptr, self); + self->native_ptr = cresult; + + pyret = Py_BuildValue("O", self); + + pylinphone_trace(-1, "[PYLINPHONE] <<< %s -> %p", __FUNCTION__, pyret); + Py_DECREF(self); + return pyret; +} + + +static void pylinphone_ChatRoom_callback_chat_message_state_changed(LinphoneChatMessage *msg, LinphoneChatMessageState state, void *ud) { + PyGILState_STATE pygil_state; + PyObject *pycm = NULL; + PyObject *_dict = (PyObject *)ud; + PyObject *_cb = PyDict_GetItemString(_dict, "callback"); + PyObject *_ud = PyDict_GetItemString(_dict, "user_data"); + + pygil_state = PyGILState_Ensure(); + pycm = pylinphone_ChatMessage_from_native_ptr(&pylinphone_ChatMessageType, msg); + pylinphone_trace(1, "[PYLINPHONE] >>> %s(%p, %p [%p], %d, %p)", __FUNCTION__, pycm, msg, state, ud); + if ((_cb != NULL) && PyCallable_Check(_cb)) { + PyObject *args = Py_BuildValue("OiO", pycm, state, _ud); + if (PyEval_CallObject(_cb, args) == NULL) { + PyErr_Print(); + } + Py_DECREF(args); + } + pylinphone_trace(-1, "[PYLINPHONE] <<< %s", __FUNCTION__); + PyGILState_Release(pygil_state); +} + +static PyObject * pylinphone_ChatRoom_instance_method_send_message2(PyObject *self, PyObject *args) { + PyObject *_chat_message; + PyObject *_dict; + PyObject *_cb; + PyObject *_ud; + LinphoneChatMessage * _chat_message_native_ptr; + LinphoneChatRoom *native_ptr = pylinphone_ChatRoom_get_native_ptr(self); + + if (native_ptr == NULL) { + PyErr_SetString(PyExc_TypeError, "Invalid linphone.ChatRoom instance"); + return NULL; + } + if (!PyArg_ParseTuple(args, "OOO", &_chat_message, &_cb, &_ud)) { + return NULL; + } + if (!PyObject_IsInstance(_chat_message, (PyObject *)&pylinphone_ChatMessageType)) { + PyErr_SetString(PyExc_TypeError, "The msg argument must be a linphone.ChatMessage"); + return NULL; + } + if ((_cb != Py_None) && !PyCallable_Check(_cb)) { + PyErr_SetString(PyExc_TypeError, "The status_cb argument must be a callable"); + return NULL; + } + if ((_chat_message_native_ptr = pylinphone_ChatMessage_get_native_ptr(_chat_message)) == NULL) { + return NULL; + } + _dict = PyDict_New(); + PyDict_SetItemString(_dict, "callback", _cb); + PyDict_SetItemString(_dict, "user_data", _ud); + + pylinphone_trace(1, "[PYLINPHONE] >>> %s(%p [%p], %p [%p], %p, %p)", __FUNCTION__, self, native_ptr, _chat_message, _chat_message_native_ptr, _cb, _ud); + linphone_chat_room_send_message2(native_ptr, _chat_message_native_ptr, pylinphone_ChatRoom_callback_chat_message_state_changed, _dict); + pylinphone_dispatch_messages(); + + pylinphone_trace(-1, "[PYLINPHONE] <<< %s -> None", __FUNCTION__); + Py_RETURN_NONE; +} + + + +static void pylinphone_VideoSize_dealloc(PyObject *self) { + pylinphone_trace(1, "[PYLINPHONE] >>> %s(%p)", __FUNCTION__, self); + self->ob_type->tp_free(self); + pylinphone_trace(-1, "[PYLINPHONE] <<< %s", __FUNCTION__); +} + +static PyObject * pylinphone_VideoSize_new(PyTypeObject *type, PyObject *args, PyObject *kw) { + pylinphone_VideoSizeObject *self = (pylinphone_VideoSizeObject *)type->tp_alloc(type, 0); + pylinphone_trace(1, "[PYLINPHONE] >>> %s()", __FUNCTION__); + pylinphone_trace(-1, "[PYLINPHONE] <<< %s -> %p", __FUNCTION__, self); + return (PyObject *)self; +} + +static int pylinphone_VideoSize_init(PyObject *self, PyObject *args, PyObject *kw) { + pylinphone_VideoSizeObject *vso = (pylinphone_VideoSizeObject *)self; + int width; + int height; + if (!PyArg_ParseTuple(args, "ii", &width, &height)) { + return -1; + } + vso->vs.width = width; + vso->vs.height = height; + return 0; +} + +static PyMemberDef pylinphone_VideoSize_members[] = { + { "width", T_INT, offsetof(pylinphone_VideoSizeObject, vs) + offsetof(MSVideoSize, width), 0, "[int] The width of the video" }, + { "height", T_INT, offsetof(pylinphone_VideoSizeObject, vs) + offsetof(MSVideoSize, height), 0, "[int] The height of the video" }, + { NULL, 0, 0, 0, NULL } /* Sentinel */ +}; + +static PyTypeObject pylinphone_VideoSizeType = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "linphone.VideoSize", /* tp_name */ + sizeof(pylinphone_VideoSizeObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + pylinphone_VideoSize_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + "Object representing the size of a video: its width and its height in pixels.", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + pylinphone_VideoSize_members, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + pylinphone_VideoSize_init, /* tp_init */ + 0, /* tp_alloc */ + pylinphone_VideoSize_new, /* tp_new */ + 0, /* tp_free */ +}; + +int PyLinphoneVideoSize_Check(PyObject *p) { + return PyObject_IsInstance(p, (PyObject *)&pylinphone_VideoSizeType); +} + +MSVideoSize PyLinphoneVideoSize_AsMSVideoSize(PyObject *obj) { + return ((pylinphone_VideoSizeObject *)obj)->vs; +} + +PyObject * PyLinphoneVideoSize_FromMSVideoSize(MSVideoSize vs) { + PyObject *linphone_module; + PyObject *pyret = NULL; + PyGILState_STATE gstate; + + gstate = PyGILState_Ensure(); + linphone_module = PyImport_ImportModule("linphone.linphone"); + if (linphone_module != NULL) { + PyObject *cls = PyObject_GetAttrString(linphone_module, "VideoSize"); + if (cls != NULL) { + PyObject *args = Py_BuildValue("ii", vs.width, vs.height); + pyret = PyEval_CallObject(cls, args); + if (pyret == NULL) { + PyErr_Print(); + } + Py_DECREF(args); + Py_DECREF(cls); + } + Py_DECREF(linphone_module); + } + PyGILState_Release(gstate); + + if (pyret == NULL) { + Py_RETURN_NONE; + } + return pyret; +} + + +time_t PyDateTime_As_time_t(PyObject *obj) { + time_t ret = -1; + PyObject *utctimetuple = PyObject_GetAttrString(obj, "utctimetuple"); + if (utctimetuple != NULL) { + PyObject *calendar_module = PyImport_ImportModule("calendar"); + if (calendar_module != NULL) { + PyObject *timegm = PyObject_GetAttrString(calendar_module, "timegm"); + if (timegm != NULL) { + PyObject *args; + PyObject *tuple; + PyObject *pyres; + args = Py_BuildValue("()"); + tuple = PyEval_CallObject(utctimetuple, args); + Py_DECREF(args); + args = Py_BuildValue("(O)", tuple); + pyres = PyEval_CallObject(timegm, args); + Py_DECREF(args); + ret = (time_t)PyLong_AsLong(pyres); + Py_DECREF(timegm); + } + Py_DECREF(calendar_module); + } + Py_DECREF(utctimetuple); + } + return ret; +} + +PyObject * PyDateTime_From_time_t(time_t t) { + PyObject *pyret = NULL; + PyObject *datetime_module; + if (t == -1) { + Py_RETURN_NONE; + } + datetime_module = PyImport_ImportModule("datetime"); + if (datetime_module != NULL) { + PyObject *datetime_class = PyObject_GetAttrString(datetime_module, "datetime"); + if (datetime_class != NULL) { + PyObject *utcfromtimestamp = PyObject_GetAttrString(datetime_class, "utcfromtimestamp"); + if (utcfromtimestamp != NULL) { + PyObject *args = Py_BuildValue("(f)", (float)t); + pyret = PyEval_CallObject(utcfromtimestamp, args); + if (pyret == NULL) { + PyErr_Print(); + } + Py_DECREF(args); + Py_DECREF(utcfromtimestamp); + } + Py_DECREF(datetime_class); + } + Py_DECREF(datetime_module); + } + if (pyret == NULL) { + Py_RETURN_NONE; + } + return pyret; +} + + +static PyObject * pylinphone_PayloadTypeType_module_method_string(PyObject *self, PyObject *args) { + const char *value_str = "[invalid]"; + int value; + PyObject *pyret; + if (!PyArg_ParseTuple(args, "i", &value)) { + return NULL; + } + pylinphone_trace(1, "[PYLINPHONE] >>> %s(%d)", __FUNCTION__, value); + switch (value) { + case PAYLOAD_AUDIO_CONTINUOUS: + value_str = "PAYLOAD_AUDIO_CONTINUOUS"; + break; + case PAYLOAD_AUDIO_PACKETIZED: + value_str = "PAYLOAD_AUDIO_PACKETIZED"; + break; + case PAYLOAD_VIDEO: + value_str = "PAYLOAD_VIDEO"; + break; + case PAYLOAD_TEXT: + value_str = "PAYLOAD_TEXT"; + break; + case PAYLOAD_OTHER: + value_str = "PAYLOAD_OTHER"; + break; + default: + break; + } + pyret = Py_BuildValue("z", value_str); + pylinphone_trace(-1, "[PYLINPHONE] <<< %s -> %p", __FUNCTION__, pyret); + return pyret; +} + +static PyMethodDef pylinphone_PayloadTypeType_ModuleMethods[] = { + { "string", pylinphone_PayloadTypeType_module_method_string, METH_VARARGS, "Get a string representation of a linphone.PayloadTypeType value." }, + /* Sentinel */ + { NULL, NULL, 0, NULL } +}; diff --git a/tools/python/apixml2python/linphone.py b/tools/python/apixml2python/linphone.py new file mode 100644 index 000000000..e90926f25 --- /dev/null +++ b/tools/python/apixml2python/linphone.py @@ -0,0 +1,1127 @@ +# Copyright (C) 2014 Belledonne Communications SARL +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +from sets import Set +import sys + + +def strip_leading_linphone(s): + if s.lower().startswith('linphone'): + return s[8:] + else: + return s + +def compute_event_name(s): + s = strip_leading_linphone(s) + s = s[4:-2] # Remove leading 'Core' and tailing 'Cb' + event_name = '' + first = True + for l in s: + if l.isupper() and not first: + event_name += '_' + event_name += l.lower() + first = False + return event_name + + +class ArgumentType: + def __init__(self, basic_type, complete_type, contained_type, linphone_module): + self.basic_type = basic_type + self.complete_type = complete_type + self.contained_type = contained_type + self.linphone_module = linphone_module + self.type_str = None + self.check_func = None + self.convert_func = None + self.convert_from_func = None + self.fmt_str = 'O' + self.cfmt_str = '%p' + self.cnativefmt_str = '%p' + self.use_native_pointer = False + self.cast_convert_func_result = True + self.__compute() + if self.basic_type == 'MSList' and self.contained_type is not None: + self.linphone_module.mslist_types.add(self.contained_type) + + def __compute(self): + splitted_type = self.complete_type.split(' ') + if self.basic_type == 'char': + if '*' in splitted_type: + self.type_str = 'string' + self.check_func = 'PyString_Check' + self.convert_func = 'PyString_AsString' + self.fmt_str = 'z' + self.cfmt_str = '\\"%s\\"' + else: + self.type_str = 'int' + self.check_func = 'PyInt_Check' + self.convert_func = 'PyInt_AsLong' + self.fmt_str = 'b' + self.cfmt_str = '%08x' + elif self.basic_type == 'int': + if 'unsigned' in splitted_type: + self.type_str = 'unsigned int' + self.check_func = 'PyInt_Check' + self.convert_func = 'PyInt_AsUnsignedLongMask' + self.fmt_str = 'I' + self.cfmt_str = '%u' + else: + self.type_str = 'int' + self.check_func = 'PyInt_Check' + self.convert_func = 'PyInt_AS_LONG' + self.fmt_str = 'i' + self.cfmt_str = '%d' + elif self.basic_type in ['int8_t', 'int16_t' 'int32_t']: + self.type_str = 'int' + self.check_func = 'PyInt_Check' + self.convert_func = 'PyInt_AS_LONG' + if self.basic_type == 'int8_t': + self.fmt_str = 'c' + elif self.basic_type == 'int16_t': + self.fmt_str = 'h' + elif self.basic_type == 'int32_t': + self.fmt_str = 'l' + self.cfmt_str = '%d' + elif self.basic_type in ['uint8_t', 'uint16_t', 'uint32_t']: + self.type_str = 'unsigned int' + self.check_func = 'PyInt_Check' + self.convert_func = 'PyInt_AsUnsignedLongMask' + if self.basic_type == 'uint8_t': + self.fmt_str = 'b' + elif self.basic_type == 'uint16_t': + self.fmt_str = 'H' + elif self.basic_type == 'uint32_t': + self.fmt_str = 'k' + self.cfmt_str = '%u' + elif self.basic_type == 'int64_t': + self.type_str = '64bits int' + self.check_func = 'PyLong_Check' + self.convert_func = 'PyLong_AsLongLong' + self.fmt_str = 'L' + self.cfmt_str = '%ld' + elif self.basic_type == 'uint64_t': + self.type_str = '64bits unsigned int' + self.check_func = 'PyLong_Check' + self.convert_func = 'PyLong_AsUnsignedLongLong' + self.fmt_str = 'K' + self.cfmt_str = '%lu' + elif self.basic_type == 'size_t': + self.type_str = 'size_t' + self.check_func = 'PyInt_Check' + self.convert_func = 'PyInt_AsSsize_t' + self.fmt_str = 'n' + self.cfmt_str = '%lu' + elif self.basic_type in ['float', 'double']: + self.type_str = 'float' + self.check_func = 'PyFloat_Check' + self.convert_func = 'PyFloat_AsDouble' + if self.basic_type == 'float': + self.fmt_str = 'f' + elif self.basic_type == 'double': + self.fmt_str = 'd' + self.cfmt_str = '%f' + elif self.basic_type == 'bool_t': + self.type_str = 'bool' + self.check_func = 'PyBool_Check' + self.convert_func = 'PyObject_IsTrue' + self.convert_from_func = 'PyBool_FromLong' + self.fmt_str = 'O' + self.cfmt_str = '%p' + self.cnativefmt_str = '%u' + elif self.basic_type == 'time_t': + self.type_str = 'DateTime' + self.check_func = 'PyDateTime_Check' + self.convert_func = 'PyDateTime_As_time_t' + self.convert_from_func = 'PyDateTime_From_time_t' + self.fmt_str = 'O' + self.cfmt_str = '%p' + self.cnativefmt_str = '%ld' + elif self.basic_type == 'MSList': + self.type_str = 'list of linphone.' + self.contained_type + self.check_func = 'PyList_Check' + self.convert_func = 'PyList_AsMSListOf' + self.contained_type + self.convert_from_func = 'PyList_FromMSListOf' + self.contained_type + self.fmt_str = 'O' + self.cfmt_str = '%p' + elif self.basic_type == 'MSVideoSize': + self.type_str = 'linphone.VideoSize' + self.check_func = 'PyLinphoneVideoSize_Check' + self.convert_func = 'PyLinphoneVideoSize_AsMSVideoSize' + self.convert_from_func = 'PyLinphoneVideoSize_FromMSVideoSize' + self.fmt_str = 'O' + self.cfmt_str = '%p' + self.cast_convert_func_result = False + else: + if strip_leading_linphone(self.basic_type) in self.linphone_module.enum_names: + self.type_str = 'int' + self.check_func = 'PyInt_Check' + self.convert_func = 'PyInt_AsLong' + self.fmt_str = 'i' + self.cfmt_str = '%d' + elif '*' in splitted_type: + self.type_str = 'linphone.' + strip_leading_linphone(self.basic_type) + self.use_native_pointer = True + else: + self.type_str = 'linphone.' + strip_leading_linphone(self.basic_type) + + +class MethodDefinition: + def __init__(self, linphone_module, class_, method_node = None): + self.body = '' + self.arg_names = [] + self.parse_tuple_format = '' + self.build_value_format = '' + self.return_type = 'void' + self.return_complete_type = 'void' + self.return_contained_type = None + self.method_node = method_node + self.class_ = class_ + self.linphone_module = linphone_module + self.self_arg = None + self.xml_method_return = None + self.xml_method_args = [] + self.method_type = 'instancemethod' + + def format_local_variables_definition(self): + body = '' + if self.xml_method_return is not None: + self.return_type = self.xml_method_return.get('type') + self.return_complete_type = self.xml_method_return.get('completetype') + self.return_contained_type = self.xml_method_return.get('containedtype') + if self.return_complete_type != 'void': + body += "\t" + self.return_complete_type + " cresult;\n" + argument_type = ArgumentType(self.return_type, self.return_complete_type, self.return_contained_type, self.linphone_module) + self.build_value_format = argument_type.fmt_str + if self.build_value_format == 'O': + body += "\tPyObject * pyresult;\n" + body += "\tPyObject * pyret;\n" + body += "\tconst char *pyret_fmt;\n" + if self.self_arg is not None: + body += "\t" + self.self_arg.get('completetype') + "native_ptr;\n" + for xml_method_arg in self.xml_method_args: + arg_name = "_" + xml_method_arg.get('name') + arg_type = xml_method_arg.get('type') + arg_complete_type = xml_method_arg.get('completetype') + arg_contained_type = xml_method_arg.get('containedtype') + argument_type = ArgumentType(arg_type, arg_complete_type, arg_contained_type, self.linphone_module) + self.parse_tuple_format += argument_type.fmt_str + if argument_type.fmt_str == 'O' and argument_type.use_native_pointer: + body += "\tPyObject * " + arg_name + ";\n" + body += "\t" + arg_complete_type + " " + arg_name + "_native_ptr = NULL;\n" + elif argument_type.fmt_str == 'O' and argument_type.convert_func is not None: + body += "\tPyObject * " + arg_name + ";\n" + body += "\t" + arg_complete_type + " " + arg_name + "_native_obj;\n" + elif strip_leading_linphone(arg_complete_type) in self.linphone_module.enum_names: + body += "\tint " + arg_name + ";\n" + else: + body += "\t" + arg_complete_type + " " + arg_name + ";\n" + self.arg_names.append(arg_name) + return body + + def format_arguments_parsing(self): + class_native_ptr_check_code = '' + if self.self_arg is not None: + class_native_ptr_check_code = self.format_class_native_pointer_check(False) + parse_tuple_code = '' + if len(self.arg_names) > 0: + parse_tuple_code = \ +"""if (!PyArg_ParseTuple(args, "{fmt}", {args})) {{ + return NULL; + }} +""".format(fmt=self.parse_tuple_format, args=', '.join(map(lambda a: '&' + a, self.arg_names))) + args_conversion_code = '' + for xml_method_arg in self.xml_method_args: + arg_name = "_" + xml_method_arg.get('name') + arg_type = xml_method_arg.get('type') + arg_complete_type = xml_method_arg.get('completetype') + arg_contained_type = xml_method_arg.get('containedtype') + argument_type = ArgumentType(arg_type, arg_complete_type, arg_contained_type, self.linphone_module) + if argument_type.fmt_str == 'O' and argument_type.convert_func is not None: + args_conversion_code += \ +""" {arg_name}_native_obj = {convert_func}({arg_name}); +""".format(arg_name=arg_name, convert_func=argument_type.convert_func) + return \ +""" {class_native_ptr_check_code} + {parse_tuple_code} + {args_type_check_code} + {args_native_ptr_check_code} + {args_conversion_code} +""".format(class_native_ptr_check_code=class_native_ptr_check_code, + parse_tuple_code=parse_tuple_code, + args_type_check_code=self.format_args_type_check(), + args_native_ptr_check_code=self.format_args_native_pointer_check(), + args_conversion_code=args_conversion_code) + + def format_enter_trace(self): + fmt = '' + args = [] + if self.self_arg is not None: + fmt += "%p [%p]" + args += ["self", "native_ptr"] + for xml_method_arg in self.xml_method_args: + arg_name = "_" + xml_method_arg.get('name') + arg_type = xml_method_arg.get('type') + arg_complete_type = xml_method_arg.get('completetype') + arg_contained_type = xml_method_arg.get('containedtype') + if fmt != '': + fmt += ', ' + argument_type = ArgumentType(arg_type, arg_complete_type, arg_contained_type, self.linphone_module) + fmt += argument_type.cfmt_str + args.append(arg_name) + if argument_type.fmt_str == 'O': + fmt += ' [' + argument_type.cnativefmt_str + ']' + if argument_type.use_native_pointer: + args.append(arg_name + '_native_ptr') + else: + args.append(arg_name + '_native_obj') + args = ', '.join(args) + if args != '': + args = ', ' + args + return "\tpylinphone_trace(1, \"[PYLINPHONE] >>> %s({fmt})\", __FUNCTION__{args});\n".format(fmt=fmt, args=args) + + def format_c_function_call(self): + arg_names = [] + c_function_call_code = '' + for xml_method_arg in self.xml_method_args: + arg_name = "_" + xml_method_arg.get('name') + arg_type = xml_method_arg.get('type') + arg_complete_type = xml_method_arg.get('completetype') + arg_contained_type = xml_method_arg.get('containedtype') + argument_type = ArgumentType(arg_type, arg_complete_type, arg_contained_type, self.linphone_module) + if argument_type.fmt_str == 'O' and argument_type.use_native_pointer: + arg_names.append(arg_name + "_native_ptr") + elif argument_type.fmt_str == 'O' and argument_type.convert_func is not None: + arg_names.append(arg_name + "_native_obj") + else: + arg_names.append(arg_name) + if self.return_type != 'void': + c_function_call_code += "cresult = " + c_function_call_code += self.method_node.get('name') + "(" + if self.self_arg is not None: + c_function_call_code += "native_ptr" + if len(arg_names) > 0: + c_function_call_code += ', ' + c_function_call_code += ', '.join(arg_names) + ");" + from_native_pointer_code = '' + convert_from_code = '' + build_value_code = '' + result_variable = '' + if self.return_complete_type != 'void': + if self.build_value_format == 'O': + stripped_return_type = strip_leading_linphone(self.return_type) + return_type_class = self.find_class_definition(self.return_type) + if return_type_class is not None: + from_native_pointer_code = "pyresult = pylinphone_{return_type}_from_native_ptr(&pylinphone_{return_type}Type, cresult);\n".format(return_type=stripped_return_type) + else: + return_argument_type = ArgumentType(self.return_type, self.return_complete_type, self.return_contained_type, self.linphone_module) + if return_argument_type.convert_from_func is not None: + convert_from_code = \ +"""pyresult = {convert_func}(cresult); +""".format(convert_func=return_argument_type.convert_from_func) + result_variable = 'pyresult' + else: + result_variable = 'cresult' + if result_variable != '': + build_value_code = "pyret = Py_BuildValue(\"{fmt}\", {result_variable});".format(fmt=self.build_value_format, result_variable=result_variable) + body = \ +""" {c_function_call_code} + pylinphone_dispatch_messages(); + {from_native_pointer_code} + {convert_from_code} + {build_value_code} +""".format(c_function_call_code=c_function_call_code, + from_native_pointer_code=from_native_pointer_code, + convert_from_code=convert_from_code, + build_value_code=build_value_code) + return body + + def format_return_trace(self): + if self.return_complete_type != 'void': + return "\tpylinphone_trace(-1, \"[PYLINPHONE] <<< %s -> %p\", __FUNCTION__, pyret);\n" + else: + return "\tpylinphone_trace(-1, \"[PYLINPHONE] <<< %s -> None\", __FUNCTION__);\n" + + def format_return_result(self): + if self.return_complete_type != 'void': + return "\treturn pyret;" + return "\tPy_RETURN_NONE;" + + def format_return_none_trace(self): + return "\tpylinphone_trace(-1, \"[PYLINPHONE] <<< %s -> None\", __FUNCTION__);\n" + + def format_class_native_pointer_check(self, return_int): + return_value = "NULL" + if return_int: + return_value = "-1" + return \ +"""native_ptr = pylinphone_{class_name}_get_native_ptr(self); + if (native_ptr == NULL) {{ + PyErr_SetString(PyExc_TypeError, "Invalid linphone.{class_name} instance"); + return {return_value}; + }} +""".format(class_name=self.class_['class_name'], return_value=return_value) + + def format_args_type_check(self): + body = '' + for xml_method_arg in self.xml_method_args: + arg_name = "_" + xml_method_arg.get('name') + arg_type = xml_method_arg.get('type') + arg_complete_type = xml_method_arg.get('completetype') + arg_contained_type = xml_method_arg.get('containedtype') + argument_type = ArgumentType(arg_type, arg_complete_type, arg_contained_type, self.linphone_module) + if argument_type.fmt_str == 'O': + if argument_type.use_native_pointer: + body += \ +""" if (({arg_name} != Py_None) && !PyObject_IsInstance({arg_name}, (PyObject *)&pylinphone_{arg_type}Type)) {{ + PyErr_SetString(PyExc_TypeError, "The '{arg_name}' argument must be a {type_str} instance."); + return NULL; + }} +""".format(arg_name=arg_name, arg_type=strip_leading_linphone(arg_type), type_str=argument_type.type_str) + else: + body += \ +""" if (!{check_func}({arg_name})) {{ + PyErr_SetString(PyExc_TypeError, "The '{arg_name}' argument must be a {type_str} instance."); + return NULL; + }} +""".format(arg_name=arg_name, check_func=argument_type.check_func, type_str=argument_type.type_str) + if body != '': + body = body[1:] # Remove leading '\t' + return body + + def format_args_native_pointer_check(self): + body = '' + for xml_method_arg in self.xml_method_args: + arg_name = "_" + xml_method_arg.get('name') + arg_type = xml_method_arg.get('type') + arg_complete_type = xml_method_arg.get('completetype') + arg_contained_type = xml_method_arg.get('containedtype') + argument_type = ArgumentType(arg_type, arg_complete_type, arg_contained_type, self.linphone_module) + if argument_type.fmt_str == 'O' and argument_type.use_native_pointer: + body += \ +""" if (({arg_name} != NULL) && ({arg_name} != Py_None)) {{ + if (({arg_name}_native_ptr = pylinphone_{arg_type}_get_native_ptr({arg_name})) == NULL) {{ + return NULL; + }} + }} +""".format(arg_name=arg_name, arg_type=strip_leading_linphone(arg_type)) + if body != '': + body = body[1:] # Remove leading '\t' + return body + + def parse_method_node(self): + if self.method_node is not None: + self.xml_method_return = self.method_node.find('./return') + self.xml_method_args = self.method_node.findall('./arguments/argument') + self.method_type = self.method_node.tag + if self.method_type != 'classmethod' and len(self.xml_method_args) > 0: + self.self_arg = self.xml_method_args[0] + self.xml_method_args = self.xml_method_args[1:] + + def remove_const_from_complete_type(self, complete_type): + splitted_type = complete_type.split(' ') + while 'const' in splitted_type: + splitted_type.remove('const') + return ' '.join(splitted_type) + + def find_class_definition(self, basic_type): + basic_type = strip_leading_linphone(basic_type) + for c in self.linphone_module.classes: + if c['class_name'] == basic_type: + return c + return None + + def format(self): + self.parse_method_node() + body = self.format_local_variables_definition() + body += self.format_arguments_parsing() + body += self.format_enter_trace() + body += self.format_c_function_call() + body += self.format_return_trace() + body += self.format_return_result() + return body + +class NewMethodDefinition(MethodDefinition): + def __init__(self, linphone_module, class_, method_node = None): + MethodDefinition.__init__(self, linphone_module, class_, method_node) + + def format_local_variables_definition(self): + return "\tpylinphone_{class_name}Object *self = (pylinphone_{class_name}Object *)type->tp_alloc(type, 0);\n".format(class_name=self.class_['class_name']) + + def format_arguments_parsing(self): + return '' + + def format_enter_trace(self): + return "\tpylinphone_trace(1, \"[PYLINPHONE] >>> %s()\", __FUNCTION__);\n" + + def format_c_function_call(self): + return '' + + def format_return_trace(self): + return "\tpylinphone_trace(-1, \"[PYLINPHONE] <<< %s -> %p\", __FUNCTION__, self);\n" + + def format_return_result(self): + return "\treturn (PyObject *)self;" + +class InitMethodDefinition(MethodDefinition): + def __init__(self, linphone_module, class_, method_node = None): + MethodDefinition.__init__(self, linphone_module, class_, method_node) + + def format_local_variables_definition(self): + return "\tpylinphone_{class_name}Object *self_obj = (pylinphone_{class_name}Object *)self;\n".format(class_name=self.class_['class_name']) + + def format_arguments_parsing(self): + return '' + + def format_enter_trace(self): + return "\tpylinphone_trace(1, \"[PYLINPHONE] >>> %s()\", __FUNCTION__);\n" + + def format_c_function_call(self): + specific_member_initialization_code = '' + for member in self.class_['class_object_members']: + specific_member_initialization_code += "\tself_obj->{member} = NULL;\n".format(member=member) + return \ +""" self_obj->native_ptr = NULL; + self_obj->user_data = NULL; +{specific_member_initialization_code} +""".format(specific_member_initialization_code=specific_member_initialization_code) + + def format_return_trace(self): + return "\tpylinphone_trace(-1, \"[PYLINPHONE] <<< %s -> %p\", __FUNCTION__, self);\n" + + def format_return_result(self): + return "\treturn 0;" + +class FromNativePointerMethodDefinition(MethodDefinition): + def __init__(self, linphone_module, class_): + MethodDefinition.__init__(self, linphone_module, class_, None) + + def format_local_variables_definition(self): + return "\tpylinphone_{class_name}Object *self = NULL;\n".format(class_name=self.class_['class_name']) + + def format_arguments_parsing(self): + return '' + + def format_enter_trace(self): + return "\tpylinphone_trace(1, \"[PYLINPHONE] >>> %s(%p)\", __FUNCTION__, native_ptr);\n" + + def format_c_function_call(self): + get_user_data_func_call = '' + set_user_data_func_call = '' + if self.class_['class_has_user_data']: + get_user_data_func_call = "self = (pylinphone_{class_name}Object *){function_prefix}get_user_data(native_ptr);".format(class_name=self.class_['class_name'], function_prefix=self.class_['class_c_function_prefix']) + set_user_data_func_call = "{function_prefix}set_user_data(self->native_ptr, self);".format(function_prefix=self.class_['class_c_function_prefix']) + ref_native_pointer_code = '' + if self.class_['class_refcountable']: + ref_native_pointer_code = "{func}(self->native_ptr);".format(func=self.class_['class_c_function_prefix'] + "ref") + return \ +""" if (native_ptr == NULL) {{ + {none_trace} + Py_RETURN_NONE; + }} + {get_user_data_func_call} + if (self == NULL) {{ + self = (pylinphone_{class_name}Object *)PyObject_CallObject((PyObject *)&pylinphone_{class_name}Type, NULL); + if (self == NULL) {{ + {none_trace} + Py_RETURN_NONE; + }} + self->native_ptr = ({class_cname} *)native_ptr; + {set_user_data_func_call} + {ref_native_pointer_code} + }} +""".format(class_name=self.class_['class_name'], class_cname=self.class_['class_cname'], + none_trace=self.format_return_none_trace(), + get_user_data_func_call=get_user_data_func_call, set_user_data_func_call=set_user_data_func_call, + ref_native_pointer_code=ref_native_pointer_code) + + def format_return_trace(self): + return "\tpylinphone_trace(-1, \"[PYLINPHONE] <<< %s -> %p\", __FUNCTION__, self);\n" + + def format_return_result(self): + return "\treturn (PyObject *)self;" + +class DeallocMethodDefinition(MethodDefinition): + def __init__(self, linphone_module, class_, method_node = None): + MethodDefinition.__init__(self, linphone_module, class_, method_node) + + def format_local_variables_definition(self): + func = "pylinphone_{class_name}_get_native_ptr".format(class_name=self.class_['class_name']) + return \ +""" {arg_type} * native_ptr = {func}(self); +""".format(arg_type=self.class_['class_cname'], func=func) + + def format_arguments_parsing(self): + # Check that the dealloc is not called a second time because of reentrancy + return "\tif (Py_REFCNT(self) < 0) return;\n" + + def format_enter_trace(self): + return "\tpylinphone_trace(1, \"[PYLINPHONE] >>> %s(%p [%p])\", __FUNCTION__, self, native_ptr);\n" + + def format_c_function_call(self): + reset_user_data_code = '' + if self.class_['class_name'] != 'Core' and self.class_['class_has_user_data']: + reset_user_data_code += \ +"""if (native_ptr != NULL) {{ + {function_prefix}set_user_data(native_ptr, NULL); + }} +""".format(function_prefix=self.class_['class_c_function_prefix']) + native_ptr_dealloc_code = '' + specific_member_decref_code = '' + if self.class_['class_refcountable']: + native_ptr_dealloc_code += \ +""" if (native_ptr != NULL) {{ + {function_prefix}unref(native_ptr); + }} +""".format(function_prefix=self.class_['class_c_function_prefix']) + elif self.class_['class_destroyable']: + native_ptr_dealloc_code += \ +""" if (native_ptr != NULL) {{ + {function_prefix}destroy(native_ptr); + }} +""".format(function_prefix=self.class_['class_c_function_prefix']) + for member in self.class_['class_object_members']: + specific_member_decref_code += "\tPy_XDECREF(((pylinphone_{class_name}Object *)self)->{member});\n".format(class_name=self.class_['class_name'], member=member) + return \ +""" {reset_user_data_code} + {native_ptr_dealloc_code} + pylinphone_dispatch_messages(); + Py_XDECREF(((pylinphone_{class_name}Object *)self)->user_data); +{specific_member_decref_code} + self->ob_type->tp_free(self); +""".format(class_name=self.class_['class_name'], reset_user_data_code=reset_user_data_code, native_ptr_dealloc_code=native_ptr_dealloc_code, specific_member_decref_code=specific_member_decref_code) + + def format_return_trace(self): + return "\tpylinphone_trace(-1, \"[PYLINPHONE] <<< %s\", __FUNCTION__);" + + def format_return_result(self): + return '' + +class GetterMethodDefinition(MethodDefinition): + def __init__(self, linphone_module, class_, method_node = None): + MethodDefinition.__init__(self, linphone_module, class_, method_node) + +class SetterMethodDefinition(MethodDefinition): + def __init__(self, linphone_module, class_, method_node = None): + MethodDefinition.__init__(self, linphone_module, class_, method_node) + + def format_arguments_parsing(self): + if self.first_argument_type.check_func is None: + attribute_type_check_code = \ +"""if ((value != Py_None) && !PyObject_IsInstance(value, (PyObject *)&pylinphone_{class_name}Type)) {{ + PyErr_SetString(PyExc_TypeError, "The '{attribute_name}' attribute value must be a linphone.{class_name} instance."); + return -1; + }} +""".format(class_name=self.first_arg_class, attribute_name=self.attribute_name) + else: + checknotnone = '' + if self.first_argument_type.type_str == 'string': + checknotnone = "(value != Py_None) && " + attribute_type_check_code = \ +"""if ({checknotnone}!{checkfunc}(value)) {{ + PyErr_SetString(PyExc_TypeError, "The '{attribute_name}' attribute value must be a {type_str}."); + return -1; + }} +""".format(checknotnone=checknotnone, checkfunc=self.first_argument_type.check_func, attribute_name=self.attribute_name, type_str=self.first_argument_type.type_str) + attribute_conversion_code = '' + if (self.first_argument_type.convert_func is None) or \ + (self.first_argument_type.fmt_str == 'O' and self.first_argument_type.convert_func is not None): + attribute_conversion_code += "{arg_name} = value;\n".format(arg_name="_" + self.first_arg_name) + if self.first_argument_type.convert_func is not None: + cast_code = '' + suffix = '' + if self.first_argument_type.cast_convert_func_result: + cast_code = "({arg_type})".format(arg_type=self.first_arg_complete_type) + if self.first_argument_type.fmt_str == 'O' and self.first_argument_type.convert_func is not None: + suffix = '_native_obj' + attribute_conversion_code += "\t{arg_name}{suffix} = {cast_code}{convertfunc}(value);\n".format( + arg_name="_" + self.first_arg_name, suffix=suffix, cast_code=cast_code, convertfunc=self.first_argument_type.convert_func) + attribute_native_ptr_check_code = '' + if self.first_argument_type.use_native_pointer: + attribute_native_ptr_check_code = \ +"""if ({arg_name} != Py_None) {{ + if (({arg_name}_native_ptr = pylinphone_{arg_class}_get_native_ptr({arg_name})) == NULL) {{ + PyErr_SetString(PyExc_TypeError, "Invalid linphone.{arg_class} instance."); + return -1; + }} + }} +""".format(arg_name="_" + self.first_arg_name, arg_class=self.first_arg_class) + return \ +""" {native_ptr_check_code} + if (value == NULL) {{ + PyErr_SetString(PyExc_TypeError, "Cannot delete the '{attribute_name}' attribute."); + return -1; + }} + {attribute_type_check_code} + {attribute_conversion_code} + {attribute_native_ptr_check_code} +""".format(attribute_name=self.attribute_name, + native_ptr_check_code=self.format_class_native_pointer_check(True), + attribute_type_check_code=attribute_type_check_code, + attribute_conversion_code=attribute_conversion_code, + attribute_native_ptr_check_code=attribute_native_ptr_check_code) + + def format_c_function_call(self): + suffix = '' + if self.first_argument_type.fmt_str == 'O' and self.first_argument_type.use_native_pointer: + suffix = '_native_ptr' + elif self.first_argument_type.fmt_str == 'O' and self.first_argument_type.convert_func is not None: + suffix = '_native_obj' + return \ +""" {method_name}(native_ptr, {arg_name}{suffix}); + pylinphone_dispatch_messages(); +""".format(arg_name="_" + self.first_arg_name, method_name=self.method_node.get('name'), suffix=suffix) + + def format_return_trace(self): + return "\tpylinphone_trace(-1, \"[PYLINPHONE] <<< %s -> 0\", __FUNCTION__);\n" + + def format_return_result(self): + return "\treturn 0;" + + def parse_method_node(self): + MethodDefinition.parse_method_node(self) + # Force return value type of setter function to prevent declaring useless local variables + # TODO: Investigate. Maybe we should decide that setters must always return an int value. + self.xml_method_return = None + self.attribute_name = self.method_node.get('property_name') + self.first_arg_type = self.xml_method_args[0].get('type') + self.first_arg_complete_type = self.xml_method_args[0].get('completetype') + self.first_arg_contained_type = self.xml_method_args[0].get('containedtype') + self.first_arg_name = self.xml_method_args[0].get('name') + self.first_argument_type = ArgumentType(self.first_arg_type, self.first_arg_complete_type, self.first_arg_contained_type, self.linphone_module) + self.first_arg_class = strip_leading_linphone(self.first_arg_type) + +class EventCallbackMethodDefinition(MethodDefinition): + def __init__(self, linphone_module, class_, method_node = None): + MethodDefinition.__init__(self, linphone_module, class_, method_node) + + def format_local_variables_definition(self): + common = \ +""" pylinphone_CoreObject *pylc = (pylinphone_CoreObject *)linphone_core_get_user_data(lc); + PyObject *func; + PyObject *args; + PyGILState_STATE pygil_state;""" + specific = '' + for xml_method_arg in self.xml_method_args: + arg_name = xml_method_arg.get('name') + arg_type = xml_method_arg.get('type') + arg_complete_type = xml_method_arg.get('completetype') + arg_contained_type = xml_method_arg.get('containedtype') + argument_type = ArgumentType(arg_type, arg_complete_type, arg_contained_type, self.linphone_module) + if argument_type.fmt_str == 'O': + specific += "\tPyObject * py" + arg_name + " = NULL;\n" + return "{common}\n{specific}".format(common=common, specific=specific) + + def format_arguments_parsing(self): + return \ +""" if (Py_REFCNT(pylc) <= 0) return; + func = PyDict_GetItemString(pylc->vtable_dict, "{name}"); + pygil_state = PyGILState_Ensure(); +""".format(name=self.class_['event_name']) + + def format_enter_trace(self): + fmt = '%p' + args = ['lc'] + for xml_method_arg in self.xml_method_args: + arg_name = xml_method_arg.get('name') + arg_type = xml_method_arg.get('type') + arg_complete_type = xml_method_arg.get('completetype') + arg_contained_type = xml_method_arg.get('containedtype') + if fmt != '': + fmt += ', ' + argument_type = ArgumentType(arg_type, arg_complete_type, arg_contained_type, self.linphone_module) + fmt += argument_type.cfmt_str + args.append(arg_name) + args=', '.join(args) + if args != '': + args = ', ' + args + return "\tpylinphone_trace(1, \"[PYLINPHONE] >>> %s({fmt})\", __FUNCTION__{args});\n".format(fmt=fmt, args=args) + + def format_c_function_call(self): + create_python_objects_code = '' + fmt = 'O' + args = ['pylc'] + for xml_method_arg in self.xml_method_args: + arg_name = xml_method_arg.get('name') + arg_type = xml_method_arg.get('type') + arg_complete_type = xml_method_arg.get('completetype') + arg_contained_type = xml_method_arg.get('containedtype') + argument_type = ArgumentType(arg_type, arg_complete_type, arg_contained_type, self.linphone_module) + fmt += argument_type.fmt_str + if argument_type.fmt_str == 'O': + args.append('py' + arg_name) + else: + args.append(arg_name) + if argument_type.fmt_str == 'O': + if argument_type.type_str == "bool": + create_python_objects_code += "\t\tpy{name} = {convert_from_func}({name});\n".format(name=arg_name, convert_from_func=argument_type.convert_from_func) + else: + type_class = self.find_class_definition(arg_type) + create_python_objects_code += "\t\tpy{name} = pylinphone_{arg_type}_from_native_ptr(&pylinphone_{arg_type}Type, {name});\n".format(name=arg_name, arg_type=strip_leading_linphone(arg_type)) + args=', '.join(args) + return \ +""" if ((func != NULL) && PyCallable_Check(func)) {{ +{create_python_objects_code} + args = Py_BuildValue("{fmt}", {args}); + if (PyEval_CallObject(func, args) == NULL) {{ + PyErr_Print(); + }} + Py_DECREF(args); + }} +""".format(fmt=fmt, args=args, create_python_objects_code=create_python_objects_code) + + def format_return_trace(self): + return "\tpylinphone_trace(-1, \"[PYLINPHONE] <<< %s\", __FUNCTION__);\n" + + def format_return_result(self): + return '\tPyGILState_Release(pygil_state);' + + def format(self): + body = MethodDefinition.format(self) + arguments = ['LinphoneCore * lc'] + for xml_method_arg in self.xml_method_args: + arg_name = xml_method_arg.get('name') + arg_type = xml_method_arg.get('type') + arg_complete_type = xml_method_arg.get('completetype') + arguments.append(arg_complete_type + ' ' + arg_name) + definition = \ +"""static void pylinphone_Core_callback_{event_name}({arguments}) {{ +{body} +}} +""".format(event_name=self.class_['event_name'], arguments=', '.join(arguments), body=body) + return definition + + +class LinphoneModule(object): + def __init__(self, tree, blacklisted_classes, blacklisted_events, blacklisted_functions, hand_written_functions): + self.internal_instance_method_names = ['destroy', 'ref', 'unref'] + self.internal_property_names = ['user_data'] + self.mslist_types = Set([]) + self.enums = [] + self.enum_names = [] + xml_enums = tree.findall("./enums/enum") + for xml_enum in xml_enums: + if xml_enum.get('deprecated') == 'true': + continue + e = {} + e['enum_name'] = strip_leading_linphone(xml_enum.get('name')) + e['enum_doc'] = self.__format_doc_content(xml_enum.find('briefdescription'), xml_enum.find('detaileddescription')) + e['enum_doc'] += "\n\nValues:\n" + e['enum_values'] = [] + xml_enum_values = xml_enum.findall("./values/value") + for xml_enum_value in xml_enum_values: + if xml_enum_value.get('deprecated') == 'true': + continue + v = {} + v['enum_value_cname'] = xml_enum_value.get('name') + v['enum_value_name'] = strip_leading_linphone(v['enum_value_cname']) + v['enum_value_doc'] = self.__format_doc(xml_enum_value.find('briefdescription'), xml_enum_value.find('detaileddescription')) + e['enum_doc'] += '\t' + v['enum_value_name'] + ': ' + v['enum_value_doc'] + '\n' + e['enum_values'].append(v) + e['enum_doc'] = self.__replace_doc_special_chars(e['enum_doc']) + self.enums.append(e) + self.enum_names.append(e['enum_name']) + self.events = [] + self.classes = [] + xml_classes = tree.findall("./classes/class") + for xml_class in xml_classes: + if xml_class.get('deprecated') == 'true': + continue + if xml_class.get('name') in blacklisted_classes: + continue + c = {} + c['class_xml_node'] = xml_class + c['class_cname'] = xml_class.get('name') + c['class_name'] = strip_leading_linphone(c['class_cname']) + c['class_c_function_prefix'] = xml_class.get('cfunctionprefix') + c['class_doc'] = self.__format_doc(xml_class.find('briefdescription'), xml_class.find('detaileddescription')) + c['class_refcountable'] = (xml_class.get('refcountable') == 'true') + c['class_destroyable'] = (xml_class.get('destroyable') == 'true') + c['class_has_user_data'] = False + c['class_type_methods'] = [] + c['class_type_hand_written_methods'] = [] + c['class_instance_hand_written_methods'] = [] + c['class_hand_written_properties'] = [] + c['class_object_members'] = [] + c['class_object_members_code'] = '' + if c['class_name'] == 'Core': + c['class_object_members'].append("vtable_dict") + c['class_object_members_code'] = "\tPyObject *vtable_dict;" + xml_events = xml_class.findall("./events/event") + for xml_event in xml_events: + if xml_event.get('deprecated') == 'true': + continue + if xml_event.get('name') in blacklisted_events: + continue + ev = {} + ev['event_xml_node'] = xml_event + ev['event_cname'] = xml_event.get('name') + ev['event_name'] = compute_event_name(ev['event_cname']) + ev['event_doc'] = self.__format_doc(xml_event.find('briefdescription'), xml_event.find('detaileddescription')) + self.events.append(ev) + xml_type_methods = xml_class.findall("./classmethods/classmethod") + for xml_type_method in xml_type_methods: + if xml_type_method.get('deprecated') == 'true': + continue + method_name = xml_type_method.get('name') + if method_name in blacklisted_functions: + continue + m = {} + m['method_name'] = method_name.replace(c['class_c_function_prefix'], '') + if method_name in hand_written_functions: + c['class_type_hand_written_methods'].append(m) + else: + m['method_xml_node'] = xml_type_method + c['class_type_methods'].append(m) + c['class_instance_methods'] = [] + xml_instance_methods = xml_class.findall("./instancemethods/instancemethod") + for xml_instance_method in xml_instance_methods: + if xml_instance_method.get('deprecated') == 'true': + continue + method_name = xml_instance_method.get('name') + if method_name in blacklisted_functions: + continue + if method_name.replace(c['class_c_function_prefix'], '') in self.internal_instance_method_names: + continue + m = {} + m['method_name'] = method_name.replace(c['class_c_function_prefix'], '') + if method_name in hand_written_functions: + c['class_instance_hand_written_methods'].append(m) + else: + m['method_xml_node'] = xml_instance_method + c['class_instance_methods'].append(m) + c['class_properties'] = [] + xml_properties = xml_class.findall("./properties/property") + for xml_property in xml_properties: + property_name = xml_property.get('name') + if property_name == 'user_data': + c['class_has_user_data'] = True + if property_name in self.internal_property_names: + continue + p = {} + p['property_name'] = property_name + xml_property_getter = xml_property.find("./getter") + xml_property_setter = xml_property.find("./setter") + handwritten_property = False + if xml_property_getter is not None: + if xml_property_getter.get('name') in blacklisted_functions or xml_property_getter.get('deprecated') == 'true': + continue + elif xml_property_getter.get('name') in hand_written_functions: + handwritten_property = True + if xml_property_setter is not None: + if xml_property_setter.get('name') in blacklisted_functions or xml_property_setter.get('deprecated') == 'true': + continue + elif xml_property_setter.get('name') in hand_written_functions: + handwritten_property = True + if handwritten_property: + p['getter_reference'] = 'NULL' + p['setter_reference'] = 'NULL' + if xml_property_getter is not None: + p['getter_reference'] = '(getter)pylinphone_' + c['class_name'] + '_get_' + p['property_name'] + if xml_property_setter is not None: + p['setter_reference'] = '(setter)pylinphone_' + c['class_name'] + '_set_' + p['property_name'] + c['class_hand_written_properties'].append(p) + else: + if xml_property_getter is not None: + xml_property_getter.set('property_name', property_name) + p['getter_name'] = xml_property_getter.get('name').replace(c['class_c_function_prefix'], '') + p['getter_xml_node'] = xml_property_getter + p['getter_reference'] = "(getter)pylinphone_" + c['class_name'] + "_" + p['getter_name'] + p['getter_definition_begin'] = "static PyObject * pylinphone_" + c['class_name'] + "_" + p['getter_name'] + "(PyObject *self, void *closure) {" + p['getter_definition_end'] = "}" + else: + p['getter_reference'] = "NULL" + if xml_property_setter is not None: + xml_property_setter.set('property_name', property_name) + p['setter_name'] = xml_property_setter.get('name').replace(c['class_c_function_prefix'], '') + p['setter_xml_node'] = xml_property_setter + p['setter_reference'] = "(setter)pylinphone_" + c['class_name'] + "_" + p['setter_name'] + p['setter_definition_begin'] = "static int pylinphone_" + c['class_name'] + "_" + p['setter_name'] + "(PyObject *self, PyObject *value, void *closure) {" + p['setter_definition_end'] = "}" + else: + p['setter_reference'] = "NULL" + c['class_properties'].append(p) + self.classes.append(c) + # Format events definitions + for ev in self.events: + ev['event_callback_definition'] = EventCallbackMethodDefinition(self, ev, ev['event_xml_node']).format() + ev['event_vtable_reference'] = "_vtable.{name} = pylinphone_Core_callback_{name};".format(name=ev['event_name']) + # Format methods' bodies + for c in self.classes: + xml_new_method = c['class_xml_node'].find("./classmethods/classmethod[@name='" + c['class_c_function_prefix'] + "new']") + try: + c['new_body'] = NewMethodDefinition(self, c, xml_new_method).format() + except Exception, e: + e.args += (c['class_name'], 'new_body') + raise + try: + c['init_body'] = InitMethodDefinition(self, c, xml_new_method).format() + except Exception, e: + e.args += (c['class_name'], 'init_body') + raise + try: + c['from_native_pointer_body'] = FromNativePointerMethodDefinition(self, c).format() + except Exception, e: + e.args += (c['class_name'], 'from_native_pointer_body') + raise + try: + for m in c['class_type_methods']: + m['method_body'] = MethodDefinition(self, c, m['method_xml_node']).format() + m['method_doc'] = self.__format_method_doc(m['method_xml_node']) + for m in c['class_instance_methods']: + m['method_body'] = MethodDefinition(self, c, m['method_xml_node']).format() + m['method_doc'] = self.__format_method_doc(m['method_xml_node']) + except Exception, e: + e.args += (c['class_name'], m['method_name']) + raise + try: + for p in c['class_properties']: + p['property_doc'] = '' + if p.has_key('setter_xml_node'): + p['setter_body'] = SetterMethodDefinition(self, c, p['setter_xml_node']).format() + p['property_doc'] = self.__format_setter_doc(p['setter_xml_node']) + if p.has_key('getter_xml_node'): + p['getter_body'] = GetterMethodDefinition(self, c, p['getter_xml_node']).format() + if p['property_doc'] == '': + p['property_doc'] = self.__format_getter_doc(p['getter_xml_node']) + except Exception, e: + e.args += (c['class_name'], p['property_name']) + raise + try: + if c['class_refcountable']: + xml_instance_method = c['class_xml_node'].find("./instancemethods/instancemethod[@name='" + c['class_c_function_prefix'] + "unref']") + c['dealloc_body'] = DeallocMethodDefinition(self, c, xml_instance_method).format() + elif c['class_destroyable']: + xml_instance_method = c['class_xml_node'].find("./instancemethods/instancemethod[@name='" + c['class_c_function_prefix'] + "destroy']") + c['dealloc_body'] = DeallocMethodDefinition(self, c, xml_instance_method).format() + else: + c['dealloc_body'] = DeallocMethodDefinition(self, c).format() + except Exception, e: + e.args += (c['class_name'], 'dealloc_body') + raise + # Convert mslist_types to a list of dictionaries for the template + d = [] + for mslist_type in self.mslist_types: + t = {} + t['c_contained_type'] = mslist_type + t['python_contained_type'] = strip_leading_linphone(mslist_type) + d.append(t) + self.mslist_types = d + + def __format_doc_node(self, node): + desc = '' + if node.tag == 'para': + if node.text is not None: + desc += node.text.strip() + for n in list(node): + desc += self.__format_doc_node(n) + elif node.tag == 'note': + if node.text is not None: + desc += node.text.strip() + for n in list(node): + desc += self.__format_doc_node(n) + elif node.tag == 'ref': + if node.text is not None: + desc += ' ' + node.text.strip() + ' ' + tail = node.tail.strip() + if tail != '': + if node.tag != 'ref': + desc += '\n' + desc += tail + if node.tag == 'para': + desc += '\n' + return desc + + def __format_doc_content(self, brief_description, detailed_description): + doc = '' + if brief_description is None: + brief_description = '' + if detailed_description is None: + detailed_description = '' + else: + desc = '' + for node in list(detailed_description): + desc += self.__format_doc_node(node) + '\n' + detailed_description = desc.strip() + brief_description = brief_description.strip() + doc += brief_description + if detailed_description != '': + if doc != '': + doc += '\n\n' + doc += detailed_description + return doc + + def __replace_doc_special_chars(self, doc): + return doc.replace('"', '').encode('string-escape') + + def __format_doc(self, brief_description, detailed_description): + doc = self.__format_doc_content(brief_description, detailed_description) + doc = self.__replace_doc_special_chars(doc) + return doc + + def __format_method_doc(self, xml_node): + doc = self.__format_doc_content(xml_node.find('briefdescription'), xml_node.find('detaileddescription')) + xml_method_return = xml_node.find('./return') + xml_method_args = xml_node.findall('./arguments/argument') + method_type = xml_node.tag + if method_type != 'classmethod' and len(xml_method_args) > 0: + xml_method_args = xml_method_args[1:] + doc += '\n' + if len(xml_method_args) > 0: + for xml_method_arg in xml_method_args: + arg_name = xml_method_arg.get('name') + arg_type = xml_method_arg.get('type') + arg_complete_type = xml_method_arg.get('completetype') + arg_contained_type = xml_method_arg.get('containedtype') + argument_type = ArgumentType(arg_type, arg_complete_type, arg_contained_type, self) + arg_doc = self.__format_doc_content(None, xml_method_arg.find('description')) + doc += '\n:param ' + arg_name + ':' + if arg_doc != '': + doc += ' ' + arg_doc + doc += '\n:type ' + arg_name + ': ' + argument_type.type_str + if xml_method_return is not None: + return_type = xml_method_return.get('type') + return_complete_type = xml_method_return.get('completetype') + return_contained_type = xml_method_return.get('containedtype') + if return_complete_type != 'void': + return_doc = self.__format_doc_content(None, xml_method_return.find('description')) + return_argument_type = ArgumentType(return_type, return_complete_type, return_contained_type, self) + doc += '\n:returns: ' + return_doc + doc += '\n:rtype: ' + return_argument_type.type_str + doc = self.__replace_doc_special_chars(doc) + return doc + + def __format_setter_doc(self, xml_node): + xml_method_arg = xml_node.findall('./arguments/argument')[1] + arg_type = xml_method_arg.get('type') + arg_complete_type = xml_method_arg.get('completetype') + arg_contained_type = xml_method_arg.get('containedtype') + argument_type = ArgumentType(arg_type, arg_complete_type, arg_contained_type, self) + doc = self.__format_doc_content(xml_node.find('briefdescription'), xml_node.find('detaileddescription')) + doc = '[' + argument_type.type_str + '] ' + doc + doc = self.__replace_doc_special_chars(doc) + return doc + + def __format_getter_doc(self, xml_node): + xml_method_return = xml_node.find('./return') + return_type = xml_method_return.get('type') + return_complete_type = xml_method_return.get('completetype') + return_contained_type = xml_method_return.get('containedtype') + return_argument_type = ArgumentType(return_type, return_complete_type, return_contained_type, self) + doc = self.__format_doc_content(xml_node.find('briefdescription'), xml_node.find('detaileddescription')) + doc = '[' + return_argument_type.type_str + '] ' + doc + doc = self.__replace_doc_special_chars(doc) + return doc diff --git a/tools/python/apixml2python/linphone_module.mustache b/tools/python/apixml2python/linphone_module.mustache new file mode 100644 index 000000000..925902da7 --- /dev/null +++ b/tools/python/apixml2python/linphone_module.mustache @@ -0,0 +1,325 @@ +/* +Copyright (C) 2014 Belledonne Communications SARL + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "gitversion.h" + +#ifdef WIN32 +#include +#endif + +#ifdef _MSC_VER +#define PYLINPHONE_INLINE __inline +#else +#define PYLINPHONE_INLINE inline +#endif + + +static void pylinphone_dispatch_messages(void); +static PYLINPHONE_INLINE void pylinphone_trace(int indent, const char *fmt, ...); + + +{{> handwritten_declarations}} + + + +{{#classes}} +static PyTypeObject pylinphone_{{class_name}}Type; +{{/classes}} + +{{#classes}} + +typedef struct { + PyObject_HEAD + PyObject *user_data; + {{class_cname}} *native_ptr; +{{{class_object_members_code}}} +} pylinphone_{{class_name}}Object; + +{{/classes}} + +{{#classes}} +static {{class_cname}} * pylinphone_{{class_name}}_get_native_ptr(PyObject *self); +static PyObject * pylinphone_{{class_name}}_from_native_ptr(PyTypeObject *type, const {{class_cname}} *native_ptr); +{{#class_type_hand_written_methods}} +static PyObject * pylinphone_{{class_name}}_class_method_{{method_name}}(PyObject *cls, PyObject *args); +{{/class_type_hand_written_methods}} +{{#class_instance_hand_written_methods}} +static PyObject * pylinphone_{{class_name}}_instance_method_{{method_name}}(PyObject *self, PyObject *args); +{{/class_instance_hand_written_methods}} +{{/classes}} + +{{#mslist_types}} +PyObject * PyList_FromMSListOf{{c_contained_type}}(const MSList *msl) { + PyObject *pyl = PyList_New(0); + while (msl != NULL) { + {{c_contained_type}} *native_ptr = ({{c_contained_type}} *)msl->data; + PyObject *item = pylinphone_{{python_contained_type}}_from_native_ptr(&pylinphone_{{python_contained_type}}Type, native_ptr); + PyList_Append(pyl, item); + msl = ms_list_next(msl); + } + return pyl; +} + +MSList * PyList_AsMSListOf{{c_contained_type}}(PyObject *pyl) { + MSList *msl = NULL; + Py_ssize_t idx; + Py_ssize_t size = PyList_Size(pyl); + for (idx = 0; idx < size; idx++) { + PyObject *item = PyList_GetItem(pyl, idx); + {{c_contained_type}} *native_ptr = pylinphone_{{python_contained_type}}_get_native_ptr(item); + msl = ms_list_append(msl, native_ptr); + } + return msl; +} + +{{/mslist_types}} + +{{#events}} +{{{event_callback_definition}}} +{{/events}} + +{{#classes}} + +static {{class_cname}} * pylinphone_{{class_name}}_get_native_ptr(PyObject *self) { + return ((pylinphone_{{class_name}}Object *)self)->native_ptr; +} + +static PyObject * pylinphone_{{class_name}}_from_native_ptr(PyTypeObject *type, const {{class_cname}} *native_ptr) { +{{{from_native_pointer_body}}} +} + +static PyObject * pylinphone_{{class_name}}_new(PyTypeObject *type, PyObject *args, PyObject *kw) { +{{{new_body}}} +} + +static int pylinphone_{{class_name}}_init(PyObject *self, PyObject *args, PyObject *kw) { +{{{init_body}}} +} + +static void pylinphone_{{class_name}}_dealloc(PyObject *self) { +{{{dealloc_body}}} +} + +{{#class_type_methods}} + +static PyObject * pylinphone_{{class_name}}_class_method_{{method_name}}(PyObject *cls, PyObject *args) { +{{{method_body}}} +} + +{{/class_type_methods}} + +{{#class_instance_methods}} + +static PyObject * pylinphone_{{class_name}}_instance_method_{{method_name}}(PyObject *self, PyObject *args) { +{{{method_body}}} +} + +{{/class_instance_methods}} + +static PyMethodDef pylinphone_{{class_name}}_methods[] = { + /* Class methods */ +{{#class_type_hand_written_methods}} + { "{{method_name}}", pylinphone_{{class_name}}_class_method_{{method_name}}, METH_VARARGS | METH_CLASS, "" }, +{{/class_type_hand_written_methods}} +{{#class_type_methods}} + { "{{method_name}}", pylinphone_{{class_name}}_class_method_{{method_name}}, METH_VARARGS | METH_CLASS, "{{{method_doc}}}" }, +{{/class_type_methods}} + /* Instance methods */ +{{#class_instance_hand_written_methods}} + { "{{method_name}}", pylinphone_{{class_name}}_instance_method_{{method_name}}, METH_VARARGS, "" }, +{{/class_instance_hand_written_methods}} +{{#class_instance_methods}} + { "{{method_name}}", pylinphone_{{class_name}}_instance_method_{{method_name}}, METH_VARARGS, "{{{method_doc}}}" }, +{{/class_instance_methods}} + /* Sentinel */ + { NULL, NULL, 0, NULL } +}; + +static PyMemberDef pylinphone_{{class_name}}_members[] = { + { "user_data", T_OBJECT, offsetof(pylinphone_{{class_name}}Object, user_data), 0, "A place to store some user data." }, + { NULL, 0, 0, 0, NULL } /* Sentinel */ +}; + +{{#class_properties}} + +{{{getter_definition_begin}}} +{{{getter_body}}} +{{{getter_definition_end}}} + +{{{setter_definition_begin}}} +{{{setter_body}}} +{{{setter_definition_end}}} + +{{/class_properties}} + +static PyGetSetDef pylinphone_{{class_name}}_getseters[] = { +{{#class_hand_written_properties}} + { "{{property_name}}", {{getter_reference}}, {{setter_reference}}, "" }, +{{/class_hand_written_properties}} +{{#class_properties}} + { "{{property_name}}", {{getter_reference}}, {{setter_reference}}, "{{{property_doc}}}" }, +{{/class_properties}} + /* Sentinel */ + { NULL, NULL, NULL, NULL, NULL } +}; + +static PyTypeObject pylinphone_{{class_name}}Type = { + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ + "linphone.{{class_name}}", /* tp_name */ + sizeof(pylinphone_{{class_name}}Object), /* tp_basicsize */ + 0, /* tp_itemsize */ + pylinphone_{{class_name}}_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + "{{{class_doc}}}", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + pylinphone_{{class_name}}_methods, /* tp_methods */ + pylinphone_{{class_name}}_members, /* tp_members */ + pylinphone_{{class_name}}_getseters, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + pylinphone_{{class_name}}_init, /* tp_init */ + 0, /* tp_alloc */ + pylinphone_{{class_name}}_new, /* tp_new */ + 0, /* tp_free */ +}; + +{{/classes}} + + +{{> handwritten_definitions}} + + +static PyMethodDef pylinphone_ModuleMethods[] = { + { "set_log_handler", pylinphone_module_method_set_log_handler, METH_VARARGS, "" }, + /* Sentinel */ + { NULL, NULL, 0, NULL } +}; + +{{#enums}} +static PyObject * pylinphone_{{enum_name}}_module_method_string(PyObject *self, PyObject *args) { + const char *value_str = "[invalid]"; + int value; + PyObject *pyret; + if (!PyArg_ParseTuple(args, "i", &value)) { + return NULL; + } + pylinphone_trace(1, "[PYLINPHONE] >>> %s(%d)", __FUNCTION__, value); + switch (value) { +{{#enum_values}} + case {{enum_value_cname}}: + value_str = "{{enum_value_name}}"; + break; +{{/enum_values}} + default: + break; + } + pyret = Py_BuildValue("z", value_str); + pylinphone_trace(-1, "[PYLINPHONE] <<< %s -> %p", __FUNCTION__, pyret); + return pyret; +} + +static PyMethodDef pylinphone_{{enum_name}}_ModuleMethods[] = { + { "string", pylinphone_{{enum_name}}_module_method_string, METH_VARARGS, "Get a string representation of a linphone.{{enum_name}} value." }, + /* Sentinel */ + { NULL, NULL, 0, NULL } +}; + +{{/enums}} + +{{> linphone_testing_module}} + +PyMODINIT_FUNC initlinphone(void) { + PyObject *m; + PyObject *menum; + + PyDateTime_IMPORT; + pylinphone_init_logging(); + +{{#classes}} + if (PyType_Ready(&pylinphone_{{class_name}}Type) < 0) return; +{{/classes}} + + /* Hand-written classes. */ + if (PyType_Ready(&pylinphone_VideoSizeType) < 0) return; + + m = Py_InitModule3("linphone", pylinphone_ModuleMethods, "Python module giving access to the Linphone library."); + if (m == NULL) return; + if (PyModule_AddStringConstant(m, "__version__", LINPHONE_GIT_REVISION) < 0) return; + +{{#enums}} + menum = Py_InitModule3("{{enum_name}}", pylinphone_{{enum_name}}_ModuleMethods, "{{{enum_doc}}}"); + if (menum == NULL) return; + Py_INCREF(menum); + if (PyModule_AddObject(m, "{{enum_name}}", menum) < 0) return; +{{#enum_values}} + if (PyModule_AddIntConstant(menum, "{{enum_value_name}}", {{enum_value_cname}}) < 0) return; +{{/enum_values}} +{{/enums}} + + menum = Py_InitModule3("PayloadTypeType", pylinphone_PayloadTypeType_ModuleMethods, "Type of linphone.PayloadType."); + if (menum == NULL) return; + Py_INCREF(menum); + if (PyModule_AddObject(m, "PayloadTypeType", menum) < 0) return; + if (PyModule_AddIntConstant(menum, "PAYLOAD_AUDIO_CONTINUOUS", PAYLOAD_AUDIO_CONTINUOUS) < 0) return; + if (PyModule_AddIntConstant(menum, "PAYLOAD_AUDIO_PACKETIZED", PAYLOAD_AUDIO_PACKETIZED) < 0) return; + if (PyModule_AddIntConstant(menum, "PAYLOAD_VIDEO", PAYLOAD_VIDEO) < 0) return; + if (PyModule_AddIntConstant(menum, "PAYLOAD_TEXT", PAYLOAD_TEXT) < 0) return; + if (PyModule_AddIntConstant(menum, "PAYLOAD_OTHER", PAYLOAD_OTHER) < 0) return; + +{{#classes}} + Py_INCREF(&pylinphone_{{class_name}}Type); + PyModule_AddObject(m, "{{class_name}}", (PyObject *)&pylinphone_{{class_name}}Type); +{{/classes}} + + /* Hand-written classes. */ + Py_INCREF(&pylinphone_VideoSizeType); + PyModule_AddObject(m, "VideoSize", (PyObject *)&pylinphone_VideoSizeType); + + pylinphone_init_testing_module(m); +} diff --git a/tools/python/apixml2python/linphone_testing_module.mustache b/tools/python/apixml2python/linphone_testing_module.mustache new file mode 100644 index 000000000..b68f8a558 --- /dev/null +++ b/tools/python/apixml2python/linphone_testing_module.mustache @@ -0,0 +1,40 @@ +#include "private.h" + +static PyObject * pylinphone_testing_module_method_set_dns_user_hosts_file(PyObject *self, PyObject *args) { + PyObject *_core; + char *_path; + LinphoneCore *_core_native_ptr; + + if (!PyArg_ParseTuple(args, "Oz", &_core, &_path)) { + return NULL; + } + if ((_core != Py_None) && !PyObject_IsInstance(_core, (PyObject *)&pylinphone_CoreType)) { + PyErr_SetString(PyExc_TypeError, "The '_core' argument must be a linphone.Core instance."); + return NULL; + } + + if ((_core != NULL) && (_core != Py_None)) { + if ((_core_native_ptr = pylinphone_Core_get_native_ptr(_core)) == NULL) { + return NULL; + } + } + + pylinphone_trace(1, "[PYLINPHONE] >>> %s(%p [%p], %s)", __FUNCTION__, _core, _core_native_ptr, _path); + sal_set_dns_user_hosts_file(_core_native_ptr->sal, _path); + pylinphone_dispatch_messages(); + + pylinphone_trace(-1, "[PYLINPHONE] <<< %s -> None", __FUNCTION__); + Py_RETURN_NONE; +} + +static PyMethodDef pylinphone_TestingModuleMethods[] = { + { "set_dns_user_hosts_file", pylinphone_testing_module_method_set_dns_user_hosts_file, METH_VARARGS, "Allows to set a user specified hosts file." }, + /* Sentinel */ + { NULL, NULL, 0, NULL } +}; + +static void pylinphone_init_testing_module(PyObject *linphone_module) { + PyObject *mtesting = Py_InitModule3("testing", pylinphone_TestingModuleMethods, "Python module adding some testing features for the Linphone library."); + Py_INCREF(mtesting); + if (PyModule_AddObject(linphone_module, "testing", mtesting) < 0) return; +} diff --git a/tools/python/doc/Makefile b/tools/python/doc/Makefile new file mode 100644 index 000000000..b8c40c718 --- /dev/null +++ b/tools/python/doc/Makefile @@ -0,0 +1,177 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = build + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Linphone.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Linphone.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/Linphone" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Linphone" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/tools/python/doc/make.bat b/tools/python/doc/make.bat new file mode 100644 index 000000000..9c081c72b --- /dev/null +++ b/tools/python/doc/make.bat @@ -0,0 +1,242 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source +set I18NSPHINXOPTS=%SPHINXOPTS% source +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% + set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :help + echo.Please use `make ^` where ^ is one of + echo. html to make standalone HTML files + echo. dirhtml to make HTML files named index.html in directories + echo. singlehtml to make a single large HTML file + echo. pickle to make pickle files + echo. json to make JSON files + echo. htmlhelp to make HTML files and a HTML help project + echo. qthelp to make HTML files and a qthelp project + echo. devhelp to make HTML files and a Devhelp project + echo. epub to make an epub + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. text to make text files + echo. man to make manual pages + echo. texinfo to make Texinfo files + echo. gettext to make PO message catalogs + echo. changes to make an overview over all changed/added/deprecated items + echo. xml to make Docutils-native XML files + echo. pseudoxml to make pseudoxml-XML files for display purposes + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + + +%SPHINXBUILD% 2> nul +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "singlehtml" ( + %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Linphone.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Linphone.ghc + goto end +) + +if "%1" == "devhelp" ( + %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. + goto end +) + +if "%1" == "epub" ( + %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub file is in %BUILDDIR%/epub. + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdf" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf + cd %BUILDDIR%/.. + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdfja" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf-ja + cd %BUILDDIR%/.. + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "text" ( + %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The text files are in %BUILDDIR%/text. + goto end +) + +if "%1" == "man" ( + %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The manual pages are in %BUILDDIR%/man. + goto end +) + +if "%1" == "texinfo" ( + %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. + goto end +) + +if "%1" == "gettext" ( + %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The message catalogs are in %BUILDDIR%/locale. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + if errorlevel 1 exit /b 1 + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + if errorlevel 1 exit /b 1 + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + if errorlevel 1 exit /b 1 + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +if "%1" == "xml" ( + %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The XML files are in %BUILDDIR%/xml. + goto end +) + +if "%1" == "pseudoxml" ( + %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. + goto end +) + +:end diff --git a/tools/python/doc/source/conf.py b/tools/python/doc/source/conf.py new file mode 100644 index 000000000..125e5c6d9 --- /dev/null +++ b/tools/python/doc/source/conf.py @@ -0,0 +1,260 @@ +# -*- coding: utf-8 -*- +# +# Linphone documentation build configuration file, created by +# sphinx-quickstart on Wed Aug 20 15:37:38 2014. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys +import os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'Linphone' +copyright = u'2014, Belledonne Communications' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '3.7' +# The full version, including alpha/beta/rc tags. +release = '3.7.0' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = [] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +#keep_warnings = False + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'default' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'Linphonedoc' + + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + ('index', 'Linphone.tex', u'Linphone Documentation', + u'Belledonne Communications', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'linphone', u'Linphone Documentation', + [u'Belledonne Communications'], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ('index', 'Linphone', u'Linphone Documentation', + u'Belledonne Communications', 'Linphone', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False diff --git a/tools/python/doc/source/index.rst b/tools/python/doc/source/index.rst new file mode 100644 index 000000000..f1c615162 --- /dev/null +++ b/tools/python/doc/source/index.rst @@ -0,0 +1,72 @@ +.. Linphone documentation master file, created by + sphinx-quickstart on Wed Aug 20 15:37:38 2014. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Linphone for Python documentation +================================= + +Getting started +--------------- + +Installing the Python module +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You can install prebuilt packages of Linphone for Python. You will find the +releases at https://pypi.python.org/pypi/linphone. This includes only packages +for the Windows platform right now. The easiest way to install is to use pip, +eg.: + +.. code-block:: none + + > pip install linphone --pre + +You can also find nightly-built packages for Windows, Mac OS X and Linux at +https://www.linphone.org/snapshots/linphone-python/. + +Otherwise you can compile the Python module. To do so get the build system code +using the command: + +.. code-block:: none + + > git clone git://git.linphone.org/linphone-cmake-builder.git + +Then follow the instructions in the *README.python* file. + +Running some code +^^^^^^^^^^^^^^^^^ + +Here is a sample source code using PyQt4 that enables you to register on a SIP +server in just a few lines of code. This is a very basic example, but it shows +how to create a linphone.Core object that is the main object of Linphone. From +there, you can use the API reference below to use more advanced feature and +perform some SIP calls, use text messaging and more... + +.. literalinclude:: pyqt_linphone_example.py + +In the Linphone Python module package you installed previously you will also +find some unit tests that you can run. These unit tests will be located in the +*site-packages/linphone/unittests/* directory of Python installation where you +installed the Linphone Python module package. To run these unit tests, follow +the instructions contained in the README.txt file of this *unittests/* +directory. + +API reference +------------- + +.. toctree:: + :maxdepth: 2 + +.. automodule:: linphone + :members: + :undoc-members: + +.. autoattribute:: linphone.__version__ + + +Indices and tables +------------------ + +* :ref:`genindex` +* :ref:`search` + diff --git a/tools/python/doc/source/pyqt_linphone_example.py b/tools/python/doc/source/pyqt_linphone_example.py new file mode 100644 index 000000000..9c214c0be --- /dev/null +++ b/tools/python/doc/source/pyqt_linphone_example.py @@ -0,0 +1,47 @@ +import linphone +import logging +import sys +from PyQt4.QtCore import QTimer +from PyQt4.QtGui import QApplication + + +def main(): + logging.basicConfig(level=logging.INFO) + + app = QApplication(sys.argv) + + def log_handler(level, msg): + method = getattr(logging, level) + method(msg) + + def global_state_changed(*args, **kwargs): + logging.warning("global_state_changed: %r %r" % (args, kwargs)) + + def registration_state_changed(core, call, state, message): + logging.warning("registration_state_changed: " + str(state) + ", " + message) + + callbacks = { + 'global_state_changed': global_state_changed, + 'registration_state_changed': registration_state_changed, + } + + linphone.set_log_handler(log_handler) + core = linphone.Core.new(callbacks, None, None) + proxy_cfg = core.create_proxy_config() + proxy_cfg.identity = "sip:toto@test.linphone.org" + proxy_cfg.server_addr = "sip:test.linphone.org" + proxy_cfg.register_enabled = True + core.add_proxy_config(proxy_cfg) + + iterate_timer = QTimer() + iterate_timer.timeout.connect(core.iterate) + stop_timer = QTimer() + stop_timer.timeout.connect(app.quit) + iterate_timer.start(20) + stop_timer.start(5000) + + exitcode = app.exec_() + sys.exit(exitcode) + + +main() diff --git a/tools/python/linphone-daemon.py b/tools/python/linphone-daemon.py new file mode 100644 index 000000000..a923c3ee9 --- /dev/null +++ b/tools/python/linphone-daemon.py @@ -0,0 +1,514 @@ +import argparse +import logging +import sys +import threading +import time +import linphone + + +class Response: + Ok = 0 + Error = 1 + + def __init__(self, status, msg = ''): + self.status = status + if status == Response.Ok: + self.body = msg + self.reason = None + else: + self.body = None + self.reason = msg + + def __str__(self): + status_str = ["Ok", "Error"][self.status] + body = '' + if self.reason: + body += "Reason: {reason}\n".format(reason=self.reason) + if self.body: + body += '\n' + self.body + '\n' + return \ +"""Status: {status} +{body}""".format(status=status_str, body=body) + +class RegisterStatusResponse(Response): + def __init__(self): + Response.__init__(self, Response.Ok) + + def append(self, id, proxy_cfg): + self.body += \ +"""Id: {id} +State: {state} +""".format(id=id, state=str(linphone.RegistrationState.string(proxy_cfg.state))) + +class CommandExample: + def __init__(self, command, output): + self.command = command + self.output = output + + def __str__(self): + return \ +"""> {command} +{output}""".format(command=self.command, output=self.output) + +class Command: + def __init__(self, name, proto): + self.name = name + self.proto = proto + self.examples = [] + + def exec_command(self, app, args): + pass + + def add_example(self, example): + self.examples.append(example) + + def help(self): + body = \ +"""{proto} + +Description: +{description} +""".format(proto=self.proto, description=self.__doc__) + idx = 0 + for example in self.examples: + idx += 1 + body += \ +""" +Example {idx}: +{example} +""".format(idx=idx, example=str(example)) + return body + +class CallCommand(Command): + """Place a call.""" + def __init__(self): + Command.__init__(self, "call", "call ") + self.add_example(CommandExample( + "call daemon-test@sip.linphone.org", + "Status: Ok\n\nId: 1" + )) + self.add_example(CommandExample( + "call daemon-test@sip.linphone.org", + "Status: Error\nReason: Call creation failed." + )) + + def exec_command(self, app, args): + if len(args) >= 1: + call = app.core.invite(args[0]) + if call is None: + app.send_response(Response(Response.Error, "Call creation failed.")) + else: + id = app.update_call_id(call) + app.send_response(Response(Response.Ok, "Id: " + str(id))) + else: + app.send_response(Response(Response.Error, "Missing parameter.")) + +class CallPauseCommand(Command): + """Pause a call (pause current if no id is specified).""" + def __init__(self): + Command.__init__(self, "call-pause", "call-pause [call-id]") + self.add_example(CommandExample( + "call-pause 1", + "Status: Ok\n\nCall was paused" + )) + self.add_example(CommandExample( + "call-pause 2", + "Status: Error\nReason: No call with such id." + )) + self.add_example(CommandExample( + "call-pause", + "Status: Error\nReason: No current call available." + )) + + def exec_command(self, app, args): + current = False + if len(args) >= 1: + call = app.find_call(args[0]) + if call is None: + app.send_response(Response(Response.Error, "No call with such id.")) + return + else: + current = True + call = app.core.current_call + if call is None: + app.send_response(Response(Response.Error, "No current call available.")) + return + if app.core.pause_call(call) == 0: + msg = "Call was paused." + if current: + msg = "Current call was paused." + app.send_response(Response(Response.Ok, msg)) + else: + app.send_response(Response(Response.Error, "Error pausing call.")) + +class CallResumeCommand(Command): + """Resume a call (resume current if no id is specified).""" + def __init__(self): + Command.__init__(self, "call-resume", "call-resume [call-id]") + self.add_example(CommandExample( + "call-resume 1", + "Status: Ok\n\nCall was resumed" + )) + self.add_example(CommandExample( + "call-resume 2", + "Status: Error\nReason: No call with such id." + )) + self.add_example(CommandExample( + "call-resume", + "Status: Error\nReason: No current call available." + )) + + def exec_command(self, app, args): + current = False + if len(args) >= 1: + call = app.find_call(args[0]) + if call is None: + app.send_response(Response(Response.Error, "No call with such id.")) + return + else: + current = True + call = app.core.current_call + if call is None: + app.send_response(Response(Response.Error, "No current call available.")) + return + if app.core.resume_call(call) == 0: + msg = "Call was resumed." + if current: + msg = "Current call was resumed." + app.send_response(Response(Response.Ok, msg)) + else: + app.send_response(Response(Response.Error, "Error resuming call.")) + +class CallStatusCommand(Command): + """Return status of the specified call or of the current call if no id is given.""" + def __init__(self): + Command.__init__(self, "call-status", "call-status [call-id]") + self.add_example(CommandExample( + "call-status 1", + "Status: Ok\n\nState: LinphoneCallStreamsRunning\nFrom: \nDirection: out\nDuration: 6" + )) + self.add_example(CommandExample( + "call-status 2", + "Status: Error\nReason: No call with such id." + )) + self.add_example(CommandExample( + "call-status", + "Status: Error\nReason: No current call available." + )) + + def exec_command(self, app, args): + if len(args) >= 1: + call = app.find_call(args[0]) + if call is None: + app.send_response(Response(Response.Error, "No call with such id.")) + return + else: + call = app.core.current_call + if call is None: + app.send_response(Response(Response.Error, "No current call available.")) + return + state = call.state + body = "State: {state}".format(state=linphone.CallState.string(state)) + if state == linphone.CallState.CallOutgoingInit \ + or state == linphone.CallState.CallOutgoingProgress \ + or state == linphone.CallState.CallOutgoingRinging \ + or state == linphone.CallState.CallPaused \ + or state == linphone.CallState.CallStreamsRunning \ + or state == linphone.CallState.CallConnected \ + or state == linphone.CallState.CallIncomingReceived: + body += "\nFrom: {address}".format(address=call.remote_address.as_string()) + if state == linphone.CallState.CallStreamsRunning \ + or state == linphone.CallState.CallConnected: + direction_str = 'in' + if call.dir == linphone.CallDir.CallOutgoing: + direction_str = 'out' + body += "\nDirection: {direction}\nDuration: {duration}".format(direction=direction_str, duration=call.duration) + app.send_response(Response(Response.Ok, body)) + +class HelpCommand(Command): + """Show help notice, if command is unspecified or inexistent show all commands.""" + def __init__(self): + Command.__init__(self, "help", "help ") + + def exec_command(self, app, args): + body = '' + if args: + command = [item for item in app.commands if item.name == args[0]] + if command: + body = command[0].help() + else: + app.send_response(Response(Response.Error, "Unknown command '{command}'.".format(command=args[0]))) + return + else: + for command in app.commands: + body += command.proto + '\n' + app.send_response(Response(Response.Ok, body)) + +class QuitCommand(Command): + """Quit the application.""" + def __init__(self): + Command.__init__(self, "quit", "quit") + + def exec_command(self, app, args): + app.quit() + app.send_response(Response(Response.Ok)) + +class RegisterCommand(Command): + """Register the daemon to a SIP proxy. If one of the parameters , and is not needed, send the string "NULL".""" + def __init__(self): + Command.__init__(self, "register", "register [password] [userid] [realm] [contact-parameters]") + self.add_example(CommandExample( + "register sip:daemon-test@sip.linphone.org sip.linphone.org password bob linphone.org", + "Status: Ok\n\nId: 1" + )) + + def exec_command(self, app, args): + if len(args) >= 2: + password = None + userid = None + realm = None + contact_parameters = None + identity = args[0] + proxy = args[1] + if len(args) > 2 and args[2] != "NULL": + password = args[2] + if len(args) > 3 and args[3] != "NULL": + userid = args[3] + if len(args) > 4 and args[4] != "NULL": + realm = args[4] + if len(args) > 5 and args[5] != "NULL": + contact_parameters = args[5] + proxy_cfg = app.core.create_proxy_config() + if password is not None: + addr = linphone.Address.new(identity) + if addr is not None: + info = linphone.AuthInfo.new(addr.username, userid, password, None, realm, None) + app.core.add_auth_info(info) + print(info) + proxy_cfg.identity = identity + proxy_cfg.server_addr = proxy + proxy_cfg.register_enabled = True + proxy_cfg.contact_parameters = contact_parameters + app.core.add_proxy_config(proxy_cfg) + id = app.update_proxy_id(proxy_cfg) + app.send_response(Response(Response.Ok, "Id: " + str(id))) + else: + app.send_response(Response(Response.Error, "Missing/Incorrect parameter(s).")) + +class RegisterStatusCommand(Command): + """Return status of a registration or of all registrations.""" + def __init__(self): + Command.__init__(self, "register-status", "register-status ") + self.add_example(CommandExample( + "register-status 1", + "Status: Ok\n\nId: 1\nState: LinphoneRegistrationOk" + )) + self.add_example(CommandExample( + "register-status ALL", + "Status: Ok\n\nId: 1\nState: LinphoneRegistrationOk\n\nId: 2\nState: LinphoneRegistrationFailed" + )) + self.add_example(CommandExample( + "register-status 3", + "Status: Error\nReason: No register with such id." + )) + + def exec_command(self, app, args): + if len(args) == 0: + app.send_response(Response(Response.Error, "Missing parameter.")) + else: + id = args[0] + if id == "ALL": + response = RegisterStatusResponse() + for id in app.proxy_ids_map: + response.append(id, app.proxy_ids_map[id]) + app.send_response(response) + else: + proxy_cfg = app.find_proxy(id) + if proxy_cfg is None: + app.send_response(Response(Response.Error, "No register with such id.")) + else: + app.send_response(RegisterStatusResponse().append(id, proxy_cfg)) + +class TerminateCommand(Command): + """Terminate the specified call or the current call if no id is given.""" + def __init__(self): + Command.__init__(self, "terminate", "terminate [call id]") + self.add_example(CommandExample( + "terminate 2", + "Status: Error\nReason: No call with such id." + )) + self.add_example(CommandExample( + "terminate 1", + "Status: Ok\n" + )) + self.add_example(CommandExample( + "terminate", + "Status: Ok\n" + )) + self.add_example(CommandExample( + "terminate", + "Status: Error\nReason: No active call." + )) + + def exec_command(self, app, args): + if len(args) >= 1: + call = app.find_call(args[0]) + if call is None: + app.send_response(Response(Response.Error, "No call with such id.")) + return + else: + call = app.core.current_call + if call is None: + app.send_response(Response(Response.Error, "No active call.")) + return + app.core.terminate_call(call) + app.send_response(Response(Response.Ok)) + + +class Daemon: + def __init__(self): + self.quitting = False + self._next_proxy_id = 1 + self.proxy_ids_map = {} + self._next_call_id = 1 + self.call_ids_map = {} + self.command_mutex = threading.Lock() + self.command_executed_event = threading.Event() + self.command_to_execute = None + self.commands = [ + CallCommand(), + CallPauseCommand(), + CallResumeCommand(), + CallStatusCommand(), + HelpCommand(), + QuitCommand(), + RegisterCommand(), + RegisterStatusCommand(), + TerminateCommand() + ] + + def global_state_changed(self, core, state, message): + logging.warning("[PYTHON] global_state_changed: " + str(state) + ", " + message) + if state == linphone.GlobalState.GlobalOn: + logging.warning("[PYTHON] core version: " + str(core.version)) + + def registration_state_changed(self, core, proxy_cfg, state, message): + logging.warning("[PYTHON] registration_state_changed: " + str(state) + ", " + message) + + def call_state_changed(self, core, call, state, message): + logging.warning("[PYTHON] call_state_changed: " + str(state) + ", " + message) + + def send_response(self, response): + print(response) + + def exec_command(self, command_line): + splitted_command_line = command_line.split() + name = splitted_command_line[0] + args = splitted_command_line[1:] + command = [item for item in self.commands if item.name == name] + if command: + command[0].exec_command(self, args) + else: + self.send_response(Response(Response.Error, "Unknown command.")) + + def interact(self): + command_line = raw_input('> ').strip() + if command_line != '': + self.command_mutex.acquire() + self.command_to_execute = command_line + self.command_mutex.release() + self.command_executed_event.wait() + self.command_executed_event.clear() + + def run(self, args): + def command_read(daemon): + while not daemon.quitting: + daemon.interact() + + callbacks = { + 'global_state_changed':self.global_state_changed, + 'registration_state_changed':self.registration_state_changed, + 'call_state_changed':self.call_state_changed + } + + # Create a linphone core and iterate every 20 ms + self.core = linphone.Core.new(callbacks, args.config, args.factory_config) + t = threading.Thread(target=command_read, kwargs={'daemon':self}) + t.start() + while not self.quitting: + self.command_mutex.acquire() + command_line = self.command_to_execute + if command_line is not None: + self.exec_command(command_line) + self.command_to_execute = None + self.command_executed_event.set() + self.command_mutex.release() + self.core.iterate() + time.sleep(0.02) + t.join() + + def quit(self): + self.quitting = True + + def update_proxy_id(self, proxy): + id = self._next_proxy_id + self.proxy_ids_map[str(id)] = proxy + self._next_proxy_id += 1 + return id + + def find_proxy(self, id): + if self.proxy_ids_map.has_key(id): + return self.proxy_ids_map[id] + return None + + def update_call_id(self, call): + id = self._next_call_id + self.call_ids_map[str(id)] = call + self._next_call_id += 1 + return id + + def find_call(self, id): + if self.call_ids_map.has_key(id): + return self.call_ids_map[id] + return None + +def setup_log_colors(): + logging.addLevelName(logging.DEBUG, "\033[1;37m%s\033[1;0m" % logging.getLevelName(logging.DEBUG)) + logging.addLevelName(logging.INFO, "\033[1;36m%s\033[1;0m" % logging.getLevelName(logging.INFO)) + logging.addLevelName(logging.WARNING, "\033[1;31m%s\033[1;0m" % logging.getLevelName(logging.WARNING)) + logging.addLevelName(logging.ERROR, "\033[1;41m%s\033[1;0m" % logging.getLevelName(logging.ERROR)) + +def setup_log(log, trace): + if log is None: + setup_log_colors() + format = "%(asctime)s.%(msecs)03d %(levelname)s: %(message)s" + datefmt = "%H:%M:%S" + if trace: + level = logging.DEBUG + else: + level = logging.INFO + logging.basicConfig(filename=log, level=level, format=format, datefmt=datefmt) + +# Define the linphone module log handler +def log_handler(level, msg): + method = getattr(logging, level) + if not msg.strip().startswith('[PYLINPHONE]'): + msg = '[CORE] ' + msg + method(msg) + +def main(argv = None): + if argv is None: + argv = sys.argv + argparser = argparse.ArgumentParser(description="Linphone console interface in Python.") + argparser.add_argument('--config', default=None, help="Path to the linphonerc configuration file to use.") + argparser.add_argument('--factory_config', default=None, help="Path to the linphonerc factory configuration file to use.") + argparser.add_argument('--log', default=None, help="Path to the file used for logging (default is the standard output).") + argparser.add_argument('--trace', action='store_true', help="Output linphone Python module tracing logs (for debug purposes).") + args = argparser.parse_args() + setup_log(args.log, args.trace) + linphone.set_log_handler(log_handler) + d = Daemon() + d.run(args) + +if __name__ == "__main__": + sys.exit(main()) diff --git a/tools/python/unittests/README.txt b/tools/python/unittests/README.txt new file mode 100644 index 000000000..f0f57a2b3 --- /dev/null +++ b/tools/python/unittests/README.txt @@ -0,0 +1,14 @@ +*************************************** +** Linphone Python module unit tests ** +*************************************** + +To run these unit tests, you need to have installed the Python module for Linphone +and to have install the nose unit tests framework. +Then use this command to run the tests: + nosetests -v --nologcapture + +The logs from the tests are put in some .log files. + +A single test file can be run by specifying it at the command line. For example, +to run only the message unit tests use: + nosetests -v --nologcapture test_message.py diff --git a/tools/python/unittests/linphonetester.py b/tools/python/unittests/linphonetester.py new file mode 100644 index 000000000..fcd485c79 --- /dev/null +++ b/tools/python/unittests/linphonetester.py @@ -0,0 +1,512 @@ +from datetime import timedelta, datetime +from nose.tools import assert_equals +from copy import deepcopy +import linphone +import logging +import os +import time + + +test_username = "liblinphone_tester" +test_password = "secret" +test_route = "sip2.linphone.org" +if os.path.isdir(os.path.join(os.path.dirname(__file__), "rcfiles")): + # Running unit tests from an installed package + tester_resources_path = os.path.abspath(os.path.dirname(__file__)) +else: + # Running unit tests from the linphone sources + tester_resources_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../../tester/")) + + +def create_address(domain): + addr = linphone.Address.new(None) + assert addr != None + addr.username = test_username + assert_equals(addr.username, test_username) + if domain is None: + domain = test_route + addr.domain = domain + assert_equals(addr.domain, domain) + addr.display_name = None + addr.display_name = "Mr Tester" + assert_equals(addr.display_name, "Mr Tester") + return addr + + +class Logger(logging.Logger): + + def __init__(self, filename): + logging.Logger.__init__(self, filename) + handler = logging.FileHandler(filename) + handler.setLevel(logging.INFO) + formatter = logging.Formatter('%(asctime)s.%(msecs)03d %(levelname)s: %(message)s', '%H:%M:%S') + handler.setFormatter(formatter) + self.addHandler(handler) + linphone.set_log_handler(self.log_handler) + + def log_handler(self, level, msg): + method = getattr(self, level) + if not msg.strip().startswith('[PYLINPHONE]'): + msg = '[CORE] ' + msg + method(msg) + + +class CoreManagerStats: + def __init__(self): + self.reset() + + def reset(self): + self.number_of_LinphoneRegistrationNone = 0 + self.number_of_LinphoneRegistrationProgress = 0 + self.number_of_LinphoneRegistrationOk = 0 + self.number_of_LinphoneRegistrationCleared = 0 + self.number_of_LinphoneRegistrationFailed = 0 + self.number_of_auth_info_requested = 0 + + self.number_of_LinphoneCallIncomingReceived = 0 + self.number_of_LinphoneCallOutgoingInit = 0 + self.number_of_LinphoneCallOutgoingProgress = 0 + self.number_of_LinphoneCallOutgoingRinging = 0 + self.number_of_LinphoneCallOutgoingEarlyMedia = 0 + self.number_of_LinphoneCallConnected = 0 + self.number_of_LinphoneCallStreamsRunning = 0 + self.number_of_LinphoneCallPausing = 0 + self.number_of_LinphoneCallPaused = 0 + self.number_of_LinphoneCallResuming = 0 + self.number_of_LinphoneCallRefered = 0 + self.number_of_LinphoneCallError = 0 + self.number_of_LinphoneCallEnd = 0 + self.number_of_LinphoneCallPausedByRemote = 0 + self.number_of_LinphoneCallUpdatedByRemote = 0 + self.number_of_LinphoneCallIncomingEarlyMedia = 0 + self.number_of_LinphoneCallUpdating = 0 + self.number_of_LinphoneCallReleased = 0 + + self.number_of_LinphoneTransferCallOutgoingInit = 0 + self.number_of_LinphoneTransferCallOutgoingProgress = 0 + self.number_of_LinphoneTransferCallOutgoingRinging = 0 + self.number_of_LinphoneTransferCallOutgoingEarlyMedia = 0 + self.number_of_LinphoneTransferCallConnected = 0 + self.number_of_LinphoneTransferCallStreamsRunning = 0 + self.number_of_LinphoneTransferCallError = 0 + + self.number_of_LinphoneMessageReceived = 0 + self.number_of_LinphoneMessageReceivedWithFile = 0 + self.number_of_LinphoneMessageReceivedLegacy = 0 + self.number_of_LinphoneMessageExtBodyReceived = 0 + self.number_of_LinphoneMessageInProgress = 0 + self.number_of_LinphoneMessageDelivered = 0 + self.number_of_LinphoneMessageNotDelivered = 0 + self.number_of_LinphoneIsComposingActiveReceived = 0 + self.number_of_LinphoneIsComposingIdleReceived = 0 + self.progress_of_LinphoneFileTransfer = 0 + + self.number_of_IframeDecoded = 0 + + self.number_of_NewSubscriptionRequest =0 + self.number_of_NotifyReceived = 0 + self.number_of_LinphonePresenceActivityOffline = 0 + self.number_of_LinphonePresenceActivityOnline = 0 + self.number_of_LinphonePresenceActivityAppointment = 0 + self.number_of_LinphonePresenceActivityAway = 0 + self.number_of_LinphonePresenceActivityBreakfast = 0 + self.number_of_LinphonePresenceActivityBusy = 0 + self.number_of_LinphonePresenceActivityDinner = 0 + self.number_of_LinphonePresenceActivityHoliday = 0 + self.number_of_LinphonePresenceActivityInTransit = 0 + self.number_of_LinphonePresenceActivityLookingForWork = 0 + self.number_of_LinphonePresenceActivityLunch = 0 + self.number_of_LinphonePresenceActivityMeal = 0 + self.number_of_LinphonePresenceActivityMeeting = 0 + self.number_of_LinphonePresenceActivityOnThePhone = 0 + self.number_of_LinphonePresenceActivityOther = 0 + self.number_of_LinphonePresenceActivityPerformance = 0 + self.number_of_LinphonePresenceActivityPermanentAbsence = 0 + self.number_of_LinphonePresenceActivityPlaying = 0 + self.number_of_LinphonePresenceActivityPresentation = 0 + self.number_of_LinphonePresenceActivityShopping = 0 + self.number_of_LinphonePresenceActivitySleeping = 0 + self.number_of_LinphonePresenceActivitySpectator = 0 + self.number_of_LinphonePresenceActivitySteering = 0 + self.number_of_LinphonePresenceActivityTravel = 0 + self.number_of_LinphonePresenceActivityTV = 0 + self.number_of_LinphonePresenceActivityUnknown = 0 + self.number_of_LinphonePresenceActivityVacation = 0 + self.number_of_LinphonePresenceActivityWorking = 0 + self.number_of_LinphonePresenceActivityWorship = 0 + self.last_received_presence = None + + self.number_of_inforeceived = 0 + + self.number_of_LinphoneSubscriptionIncomingReceived = 0 + self.number_of_LinphoneSubscriptionOutgoingInit = 0 + self.number_of_LinphoneSubscriptionPending = 0 + self.number_of_LinphoneSubscriptionActive = 0 + self.number_of_LinphoneSubscriptionTerminated = 0 + self.number_of_LinphoneSubscriptionError = 0 + self.number_of_LinphoneSubscriptionExpiring = 0 + + self.number_of_LinphonePublishProgress = 0 + self.number_of_LinphonePublishOk = 0 + self.number_of_LinphonePublishExpiring = 0 + self.number_of_LinphonePublishError = 0 + self.number_of_LinphonePublishCleared = 0 + + self.number_of_LinphoneConfiguringSkipped = 0 + self.number_of_LinphoneConfiguringFailed = 0 + self.number_of_LinphoneConfiguringSuccessful = 0 + + self.number_of_LinphoneCallEncryptedOn = 0 + self.number_of_LinphoneCallEncryptedOff = 0 + + +class CoreManager: + + @classmethod + def wait_for_until(cls, manager1, manager2, func, timeout): + managers = [] + if manager1 is not None: + managers.append(manager1) + if manager2 is not None: + managers.append(manager2) + return cls.wait_for_list(managers, func, timeout) + + @classmethod + def wait_for_list(cls, managers, func, timeout): + start = datetime.now() + end = start + timedelta(milliseconds = timeout) + res = func(*managers) + while not res and datetime.now() < end: + for manager in managers: + manager.lc.iterate() + time.sleep(0.02) + res = func(*managers) + return res + + @classmethod + def wait_for(cls, manager1, manager2, func): + return cls.wait_for_until(manager1, manager2, func, 10000) + + @classmethod + def call(cls, caller_manager, callee_manager, caller_params = None, callee_params = None, build_callee_params = False): + initial_caller_stats = deepcopy(caller_manager.stats) + initial_callee_stats = deepcopy(callee_manager.stats) + + # Use playfile for callee to avoid locking on capture card + callee_manager.lc.use_files = True + callee_manager.lc.play_file = os.path.join(tester_resources_path, 'sounds', 'hello8000.wav') + + if caller_params is None: + call = caller_manager.lc.invite_address(callee_manager.identity) + else: + call = caller_manager.lc.invite_address_with_params(callee_manager.identity, caller_params) + assert call is not None + + assert_equals(CoreManager.wait_for(callee_manager, caller_manager, + lambda callee_manager, caller_manager: callee_manager.stats.number_of_LinphoneCallIncomingReceived == initial_callee_stats.number_of_LinphoneCallIncomingReceived + 1), True) + assert_equals(callee_manager.lc.incoming_invite_pending, True) + assert_equals(caller_manager.stats.number_of_LinphoneCallOutgoingProgress, initial_caller_stats.number_of_LinphoneCallOutgoingProgress + 1) + + retry = 0 + while (caller_manager.stats.number_of_LinphoneCallOutgoingRinging != initial_caller_stats.number_of_LinphoneCallOutgoingRinging + 1) and \ + (caller_manager.stats.number_of_LinphoneCallOutgoingEarlyMedia != initial_caller_stats.number_of_LinphoneCallOutgoingEarlyMedia + 1) and \ + retry < 20: + retry += 1 + caller_manager.lc.iterate() + callee_manager.lc.iterate() + time.sleep(0.1) + assert ((caller_manager.stats.number_of_LinphoneCallOutgoingRinging == initial_caller_stats.number_of_LinphoneCallOutgoingRinging + 1) or \ + (caller_manager.stats.number_of_LinphoneCallOutgoingEarlyMedia == initial_caller_stats.number_of_LinphoneCallOutgoingEarlyMedia + 1)) == True + + assert callee_manager.lc.current_call_remote_address is not None + if caller_manager.lc.current_call is None or callee_manager.lc.current_call is None or callee_manager.lc.current_call_remote_address is None: + return False + callee_from_address = caller_manager.identity.clone() + callee_from_address.port = 0 # Remove port because port is never present in from header + assert_equals(callee_from_address.weak_equal(callee_manager.lc.current_call_remote_address), True) + + if callee_params is not None: + callee_manager.lc.accept_call_with_params(callee_manager.lc.current_call, callee_params) + elif build_callee_params: + default_params = callee_manager.lc.create_call_params(callee_manager.lc.current_call) + callee_manager.lc.accept_call_with_params(callee_manager.lc.current_call, default_params) + else: + callee_manager.lc.accept_call(callee_manager.lc.current_call) + assert_equals(CoreManager.wait_for(callee_manager, caller_manager, + lambda callee_manager, caller_manager: (callee_manager.stats.number_of_LinphoneCallConnected == initial_callee_stats.number_of_LinphoneCallConnected + 1) and \ + (caller_manager.stats.number_of_LinphoneCallConnected == initial_caller_stats.number_of_LinphoneCallConnected + 1)), True) + # Just to sleep + result = CoreManager.wait_for(callee_manager, caller_manager, + lambda callee_manager, caller_manager: (callee_manager.stats.number_of_LinphoneCallStreamsRunning == initial_callee_stats.number_of_LinphoneCallStreamsRunning + 1) and \ + (caller_manager.stats.number_of_LinphoneCallStreamsRunning == initial_caller_stats.number_of_LinphoneCallStreamsRunning + 1)) + + if caller_manager.lc.media_encryption != linphone.MediaEncryption.MediaEncryptionNone and callee_manager.lc.media_encryption != linphone.MediaEncryption.MediaEncryptionNone: + # Wait for encryption to be on, in case of zrtp, it can take a few seconds + if caller_manager.lc.media_encryption == linphone.MediaEncryption.MediaEncryptionZRTP: + CoreManager.wait_for(callee_manager, caller_manager, + lambda callee_manager, caller_manager: caller_manager.stats.number_of_LinphoneCallEncryptedOn == initial_caller_stats.number_of_LinphoneCallEncryptedOn + 1) + if callee_manager.lc.media_encryption == linphone.MediaEncryption.MediaEncryptionZRTP: + CoreManager.wait_for(callee_manager, caller_manager, + lambda callee_manager, caller_manager: callee_manager.stats.number_of_LinphoneCallEncryptedOn == initial_callee_stats.number_of_LinphoneCallEncryptedOn + 1) + assert_equals(callee_manager.lc.current_call.current_params.media_encryption, caller_manager.lc.media_encryption) + assert_equals(caller_manager.lc.current_call.current_params.media_encryption, callee_manager.lc.media_encryption) + + return result + + @classmethod + def end_call(cls, caller_manager, callee_manager): + caller_manager.lc.terminate_all_calls() + assert_equals(CoreManager.wait_for(caller_manager, callee_manager, + lambda caller_manager, callee_manager: caller_manager.stats.number_of_LinphoneCallEnd == 1 and callee_manager.stats.number_of_LinphoneCallEnd == 1), True) + + @classmethod + def registration_state_changed(cls, lc, cfg, state, message): + manager = lc.user_data + if manager.logger is not None: + manager.logger.info("[TESTER] New registration state {state} for user id [{identity}] at proxy [{addr}]".format( + state=linphone.RegistrationState.string(state), identity=cfg.identity, addr=cfg.server_addr)) + if state == linphone.RegistrationState.RegistrationNone: + manager.stats.number_of_LinphoneRegistrationNone += 1 + elif state == linphone.RegistrationState.RegistrationProgress: + manager.stats.number_of_LinphoneRegistrationProgress += 1 + elif state == linphone.RegistrationState.RegistrationOk: + manager.stats.number_of_LinphoneRegistrationOk += 1 + elif state == linphone.RegistrationState.RegistrationCleared: + manager.stats.number_of_LinphoneRegistrationCleared += 1 + elif state == linphone.RegistrationState.RegistrationFailed: + manager.stats.number_of_LinphoneRegistrationFailed += 1 + else: + raise Exception("Unexpected registration state") + + @classmethod + def auth_info_requested(cls, lc, realm, username, domain): + manager = lc.user_data + if manager.logger is not None: + manager.logger.info("[TESTER] Auth info requested for user id [{username}] at realm [{realm}]".format( + username=username, realm=realm)) + manager.stats.number_of_auth_info_requested +=1 + + @classmethod + def call_state_changed(cls, lc, call, state, msg): + manager = lc.user_data + to_address = call.call_log.to_address.as_string() + from_address = call.call_log.from_address.as_string() + direction = "Outgoing" + if call.call_log.dir == linphone.CallDir.CallIncoming: + direction = "Incoming" + if manager.logger is not None: + manager.logger.info("[TESTER] {direction} call from [{from_address}] to [{to_address}], new state is [{state}]".format( + direction=direction, from_address=from_address, to_address=to_address, state=linphone.CallState.string(state))) + if state == linphone.CallState.CallIncomingReceived: + manager.stats.number_of_LinphoneCallIncomingReceived += 1 + elif state == linphone.CallState.CallOutgoingInit: + manager.stats.number_of_LinphoneCallOutgoingInit += 1 + elif state == linphone.CallState.CallOutgoingProgress: + manager.stats.number_of_LinphoneCallOutgoingProgress += 1 + elif state == linphone.CallState.CallOutgoingRinging: + manager.stats.number_of_LinphoneCallOutgoingRinging += 1 + elif state == linphone.CallState.CallOutgoingEarlyMedia: + manager.stats.number_of_LinphoneCallOutgoingEarlyMedia += 1 + elif state == linphone.CallState.CallConnected: + manager.stats.number_of_LinphoneCallConnected += 1 + elif state == linphone.CallState.CallStreamsRunning: + manager.stats.number_of_LinphoneCallStreamsRunning += 1 + elif state == linphone.CallState.CallPausing: + manager.stats.number_of_LinphoneCallPausing += 1 + elif state == linphone.CallState.CallPaused: + manager.stats.number_of_LinphoneCallPaused += 1 + elif state == linphone.CallState.CallResuming: + manager.stats.number_of_LinphoneCallResuming += 1 + elif state == linphone.CallState.CallRefered: + manager.stats.number_of_LinphoneCallRefered += 1 + elif state == linphone.CallState.CallError: + manager.stats.number_of_LinphoneCallError += 1 + elif state == linphone.CallState.CallEnd: + manager.stats.number_of_LinphoneCallEnd += 1 + elif state == linphone.CallState.CallPausedByRemote: + manager.stats.number_of_LinphoneCallPausedByRemote += 1 + elif state == linphone.CallState.CallUpdatedByRemote: + manager.stats.number_of_LinphoneCallUpdatedByRemote += 1 + elif state == linphone.CallState.CallIncomingEarlyMedia: + manager.stats.number_of_LinphoneCallIncomingEarlyMedia += 1 + elif state == linphone.CallState.CallUpdating: + manager.stats.number_of_LinphoneCallUpdating += 1 + elif state == linphone.CallState.CallReleased: + manager.stats.number_of_LinphoneCallReleased += 1 + else: + raise Exception("Unexpected call state") + + @classmethod + def message_received(cls, lc, room, message): + manager = lc.user_data + from_str = message.from_address.as_string() + text_str = message.text + external_body_url = message.external_body_url + if manager.logger is not None: + manager.logger.info("[TESTER] Message from [{from_str}] is [{text_str}], external URL [{external_body_url}]".format( + from_str=from_str, text_str=text_str, external_body_url=external_body_url)) + manager.stats.number_of_LinphoneMessageReceived += 1 + + if message.external_body_url is not None: + manager.stats.number_of_LinphoneMessageExtBodyReceived += 1 + + @classmethod + def new_subscription_requested(cls, lc, lf, url): + manager = lc.user_data + if manager.logger is not None: + manager.logger.info("[TESTER] New subscription request: from [{from_str}], url [{url}]".format( + from_str=lf.address.as_string(), url=url)) + manager.stats.number_of_NewSubscriptionRequest += 1 + lc.add_friend(lf) # Accept subscription + + @classmethod + def notify_presence_received(cls, lc, lf): + manager = lc.user_data + if manager.logger is not None: + manager.logger.info("[TESTER] New notify request: from [{from_str}]".format( + from_str=lf.address.as_string())) + manager.stats.number_of_NotifyReceived += 1 + manager.stats.last_received_presence = lf.presence_model + acttype = manager.stats.last_received_presence.activity.type + if acttype == linphone.PresenceActivityType.PresenceActivityOffline: + manager.stats.number_of_LinphonePresenceActivityOffline += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityOnline: + manager.stats.number_of_LinphonePresenceActivityOnline += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityAppointment: + manager.stats.number_of_LinphonePresenceActivityAppointment += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityAway: + manager.stats.number_of_LinphonePresenceActivityAway += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityBreakfast: + manager.stats.number_of_LinphonePresenceActivityBreakfast += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityBusy: + manager.stats.number_of_LinphonePresenceActivityBusy += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityDinner: + manager.stats.number_of_LinphonePresenceActivityDinner += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityHoliday: + manager.stats.number_of_LinphonePresenceActivityHoliday += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityInTransit: + manager.stats.number_of_LinphonePresenceActivityInTransit += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityLookingForWork: + manager.stats.number_of_LinphonePresenceActivityLookingForWork += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityLunch: + manager.stats.number_of_LinphonePresenceActivityLunch += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityMeal: + manager.stats.number_of_LinphonePresenceActivityMeal += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityMeeting: + manager.stats.number_of_LinphonePresenceActivityMeeting += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityOnThePhone: + manager.stats.number_of_LinphonePresenceActivityOnThePhone += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityOther: + manager.stats.number_of_LinphonePresenceActivityOther += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityPerformance: + manager.stats.number_of_LinphonePresenceActivityPerformance += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityPermanentAbsence: + manager.stats.number_of_LinphonePresenceActivityPermanentAbsence += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityPlaying: + manager.stats.number_of_LinphonePresenceActivityPlaying += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityPresentation: + manager.stats.number_of_LinphonePresenceActivityPresentation += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityShopping: + manager.stats.number_of_LinphonePresenceActivityShopping += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivitySleeping: + manager.stats.number_of_LinphonePresenceActivitySleeping += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivitySpectator: + manager.stats.number_of_LinphonePresenceActivitySpectator += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivitySteering: + manager.stats.number_of_LinphonePresenceActivitySteering += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityTravel: + manager.stats.number_of_LinphonePresenceActivityTravel += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityTV: + manager.stats.number_of_LinphonePresenceActivityTV += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityUnknown: + manager.stats.number_of_LinphonePresenceActivityUnknown += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityVacation: + manager.stats.number_of_LinphonePresenceActivityVacation += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityWorking: + manager.stats.number_of_LinphonePresenceActivityWorking += 1 + elif acttype == linphone.PresenceActivityType.PresenceActivityWorship: + manager.stats.number_of_LinphonePresenceActivityWorship += 1 + + def __init__(self, rc_file = None, check_for_proxies = True, vtable = {}, logger=None): + self.logger = logger + if not vtable.has_key('registration_state_changed'): + vtable['registration_state_changed'] = CoreManager.registration_state_changed + if not vtable.has_key('auth_info_requested'): + vtable['auth_info_requested'] = CoreManager.auth_info_requested + if not vtable.has_key('call_state_changed'): + vtable['call_state_changed'] = CoreManager.call_state_changed + if not vtable.has_key('message_received'): + vtable['message_received'] = CoreManager.message_received + #if not vtable.has_key('file_transfer_recv'): + #vtable['file_transfer_recv'] = CoreManager.file_transfer_recv + #if not vtable.has_key('file_transfer_send'): + #vtable['file_transfer_send'] = CoreManager.file_transfer_send + #if not vtable.has_key('file_transfer_progress_indication'): + #vtable['file_transfer_progress_indication'] = CoreManager.file_transfer_progress_indication + #if not vtable.has_key('is_composing_received'): + #vtable['is_composing_received'] = CoreManager.is_composing_received + if not vtable.has_key('new_subscription_requested'): + vtable['new_subscription_requested'] = CoreManager.new_subscription_requested + if not vtable.has_key('notify_presence_received'): + vtable['notify_presence_received'] = CoreManager.notify_presence_received + #if not vtable.has_key('transfer_state_changed'): + #vtable['transfer_state_changed'] = CoreManager.transfer_state_changed + #if not vtable.has_key('info_received'): + #vtable['info_received'] = CoreManager.info_received + #if not vtable.has_key('subscription_state_changed'): + #vtable['subscription_state_changed'] = CoreManager.subscription_state_changed + #if not vtable.has_key('notify_received'): + #vtable['notify_received'] = CoreManager.notify_received + #if not vtable.has_key('publish_state_changed'): + #vtable['publish_state_changed'] = CoreManager.publish_state_changed + #if not vtable.has_key('configuring_status'): + #vtable['configuring_status'] = CoreManager.configuring_status + #if not vtable.has_key('call_encryption_changed'): + #vtable['call_encryption_changed'] = CoreManager.call_encryption_changed + self.identity = None + self.stats = CoreManagerStats() + rc_path = None + if rc_file is not None: + rc_path = os.path.join('rcfiles', rc_file) + self.lc = self.configure_lc_from(vtable, tester_resources_path, rc_path) + self.lc.user_data = self + if check_for_proxies and rc_file is not None: + proxy_count = len(self.lc.proxy_config_list) + else: + proxy_count = 0 + if proxy_count: + CoreManager.wait_for_until(self, None, lambda manager: manager.stats.number_of_LinphoneRegistrationOk == proxy_count, 5000 * proxy_count) + assert_equals(self.stats.number_of_LinphoneRegistrationOk, proxy_count) + self.enable_audio_codec("PCMU", 8000) + + if self.lc.default_proxy_config is not None: + self.identity = linphone.Address.new(self.lc.default_proxy_config.identity) + self.identity.clean() + + def stop(self): + self.lc = None + + def configure_lc_from(self, vtable, resources_path, rc_path): + filepath = None + if rc_path is not None: + filepath = os.path.join(resources_path, rc_path) + assert_equals(os.path.isfile(filepath), True) + lc = linphone.Core.new(vtable, None, filepath) + linphone.testing.set_dns_user_hosts_file(lc, os.path.join(resources_path, 'tester_hosts')) + lc.root_ca = os.path.join(resources_path, 'certificates', 'cn', 'cafile.pem') + lc.ring = os.path.join(resources_path, 'sounds', 'oldphone.wav') + lc.ringback = os.path.join(resources_path, 'sounds', 'ringback.wav') + lc.static_picture = os.path.join(resources_path, 'images', 'nowebcamCIF.jpg') + return lc + + def enable_audio_codec(self, mime, rate): + codecs = self.lc.audio_codecs + for codec in codecs: + self.lc.enable_payload_type(codec, False) + codec = self.lc.find_payload_type(mime, rate, 1) + assert codec is not None + if codec is not None: + self.lc.enable_payload_type(codec, True) + + def disable_all_audio_codecs_except_one(self, mime): + self.enable_audio_codec(mime, -1) diff --git a/tools/python/unittests/test_call.py b/tools/python/unittests/test_call.py new file mode 100644 index 000000000..93dfd1175 --- /dev/null +++ b/tools/python/unittests/test_call.py @@ -0,0 +1,116 @@ +from nose.tools import assert_equals +import linphone +from linphonetester import * +import os +import time + + +class TestCall: + + @classmethod + def setup_class(cls): + base, ext = os.path.splitext(os.path.basename(__file__)) + cls.logger = Logger(base + '.log') + + def test_early_declined_call(self): + marie = CoreManager('marie_rc', logger=TestCall.logger) + pauline = CoreManager('pauline_rc', logger=TestCall.logger) + marie.lc.max_calls = 0 + out_call = pauline.lc.invite('marie') + + # Wait until flexisip transfers the busy... + assert_equals(CoreManager.wait_for_until(pauline, marie, lambda pauline, marie: pauline.stats.number_of_LinphoneCallError == 1, 33000), True) + assert_equals(pauline.stats.number_of_LinphoneCallError, 1) + assert_equals(out_call.reason, linphone.Reason.ReasonBusy) + if len(pauline.lc.call_logs) > 0: + out_call_log = pauline.lc.call_logs[0] + assert out_call_log is not None + assert_equals(out_call_log.status, linphone.CallStatus.CallAborted) + marie.stop() + pauline.stop() + + def test_declined_call(self): + marie = CoreManager('marie_rc', logger=TestCall.logger) + pauline = CoreManager('pauline_rc', logger=TestCall.logger) + out_call = pauline.lc.invite_address(marie.identity) + assert_equals(CoreManager.wait_for(pauline, marie, lambda pauline, marie: marie.stats.number_of_LinphoneCallIncomingReceived == 1), True) + in_call = marie.lc.current_call + assert in_call is not None + if in_call is not None: + marie.lc.terminate_call(in_call) + assert_equals(CoreManager.wait_for(pauline, marie, lambda pauline, marie: marie.stats.number_of_LinphoneCallReleased == 1), True) + assert_equals(CoreManager.wait_for(pauline, marie, lambda pauline, marie: pauline.stats.number_of_LinphoneCallReleased == 1), True) + assert_equals(marie.stats.number_of_LinphoneCallEnd, 1) + assert_equals(pauline.stats.number_of_LinphoneCallEnd, 1) + assert_equals(in_call.reason, linphone.Reason.ReasonDeclined) + assert_equals(out_call.reason, linphone.Reason.ReasonDeclined) + marie.stop() + pauline.stop() + + def test_cancelled_call(self): + marie = CoreManager('marie_rc', logger=TestCall.logger) + pauline = CoreManager('pauline_rc', logger=TestCall.logger) + out_call = pauline.lc.invite('marie') + assert_equals(CoreManager.wait_for(pauline, marie, lambda pauline, marie: pauline.stats.number_of_LinphoneCallOutgoingInit == 1), True) + pauline.lc.terminate_call(out_call) + assert_equals(CoreManager.wait_for(pauline, marie, lambda pauline, marie: pauline.stats.number_of_LinphoneCallEnd == 1), True) + assert_equals(pauline.stats.number_of_LinphoneCallEnd, 1) + assert_equals(marie.stats.number_of_LinphoneCallIncomingReceived, 0) + assert_equals(CoreManager.wait_for(pauline, marie, lambda pauline, marie: pauline.stats.number_of_LinphoneCallReleased == 1), True) + marie.stop() + pauline.stop() + + def test_early_cancelled_call(self): + marie = CoreManager('marie_rc', logger=TestCall.logger) + pauline = CoreManager('empty_rc', check_for_proxies=False, logger=TestCall.logger) + out_call = pauline.lc.invite_address(marie.identity) + assert_equals(CoreManager.wait_for(pauline, marie, lambda pauline, marie: pauline.stats.number_of_LinphoneCallOutgoingInit == 1), True) + pauline.lc.terminate_call(out_call) + + # Since everything is executed in a row, no response can be received from the server, thus the CANCEL cannot be sent. + # It will ring at Marie's side. + assert_equals(CoreManager.wait_for(pauline, marie, lambda pauline, marie: pauline.stats.number_of_LinphoneCallEnd == 1), True) + assert_equals(pauline.stats.number_of_LinphoneCallEnd, 1) + assert_equals(CoreManager.wait_for(pauline, marie, lambda pauline, marie: marie.stats.number_of_LinphoneCallIncomingReceived == 1), True) + + # Now the CANCEL should have been sent and the the call at marie's side should terminate + assert_equals(CoreManager.wait_for(pauline, marie, lambda pauline, marie: marie.stats.number_of_LinphoneCallEnd == 1), True) + assert_equals(CoreManager.wait_for(pauline, marie, lambda pauline, marie: pauline.stats.number_of_LinphoneCallReleased == 1), True) + marie.stop() + pauline.stop() + + def test_cancelled_ringing_call(self): + marie = CoreManager('marie_rc', logger=TestCall.logger) + pauline = CoreManager('pauline_rc', logger=TestCall.logger) + out_call = pauline.lc.invite('marie') + assert_equals(CoreManager.wait_for(pauline, marie, lambda pauline, marie: marie.stats.number_of_LinphoneCallIncomingReceived == 1), True) + pauline.lc.terminate_call(out_call) + assert_equals(CoreManager.wait_for(pauline, marie, lambda pauline, marie: (pauline.stats.number_of_LinphoneCallReleased == 1) and (marie.stats.number_of_LinphoneCallReleased == 1)), True) + assert_equals(marie.stats.number_of_LinphoneCallEnd, 1) + assert_equals(pauline.stats.number_of_LinphoneCallEnd, 1) + marie.stop() + pauline.stop() + + def test_call_failed_because_of_codecs(self): + marie = CoreManager('marie_rc', logger=TestCall.logger) + pauline = CoreManager('pauline_rc', logger=TestCall.logger) + marie.disable_all_audio_codecs_except_one('pcmu') + pauline.disable_all_audio_codecs_except_one('pcma') + out_call = pauline.lc.invite('marie') + assert_equals(CoreManager.wait_for(pauline, marie, lambda pauline, marie: pauline.stats.number_of_LinphoneCallOutgoingInit == 1), True) + + # flexisip will retain the 488 until the "urgent reply" timeout arrives. + assert_equals(CoreManager.wait_for_until(pauline, marie, lambda pauline, marie: pauline.stats.number_of_LinphoneCallError == 1, 6000), True) + assert_equals(out_call.reason, linphone.Reason.ReasonNotAcceptable) + assert_equals(marie.stats.number_of_LinphoneCallIncomingReceived, 0) + marie.stop() + pauline.stop() + + def test_simple_call(self): + marie = CoreManager('marie_rc', logger=TestCall.logger) + pauline = CoreManager('pauline_rc', logger=TestCall.logger) + assert_equals(CoreManager.call(pauline, marie), True) + #liblinphone_tester_check_rtcp(marie,pauline); + CoreManager.end_call(marie, pauline) + marie.stop() + pauline.stop() diff --git a/tools/python/unittests/test_message.py b/tools/python/unittests/test_message.py new file mode 100644 index 000000000..56a7e9e17 --- /dev/null +++ b/tools/python/unittests/test_message.py @@ -0,0 +1,46 @@ +from nose.tools import assert_equals +from copy import deepcopy +import linphone +from linphonetester import * +import os +import time + + +class TestMessage: + + @classmethod + def setup_class(cls): + base, ext = os.path.splitext(os.path.basename(__file__)) + cls.logger = Logger(base + '.log') + + def wait_for_server_to_purge_messages(self, manager1, manager2): + # Wait a little bit just to have time to purge message stored in the server + CoreManager.wait_for_until(manager1, manager2, lambda manager1, manager2: False, 100) + manager1.stats.reset() + manager2.stats.reset() + + def test_text_message(self): + marie = CoreManager('marie_rc', logger=TestMessage.logger) + pauline = CoreManager('pauline_rc', logger=TestMessage.logger) + chat_room = pauline.lc.get_chat_room(marie.identity) + self.wait_for_server_to_purge_messages(marie, pauline) + msg = chat_room.create_message("Bla bla bla bla") + chat_room.send_message2(msg, None, None) + assert_equals(CoreManager.wait_for(pauline, marie, lambda pauline, marie: marie.stats.number_of_LinphoneMessageReceived == 1), True) + assert marie.lc.get_chat_room(pauline.identity) is not None + marie.stop() + pauline.stop() + + def test_text_message_within_dialog(self): + marie = CoreManager('marie_rc', logger=TestMessage.logger) + pauline = CoreManager('pauline_rc', logger=TestMessage.logger) + pauline.lc.config.set_int('sip', 'chat_use_call_dialogs', 1) + chat_room = pauline.lc.get_chat_room(marie.identity) + self.wait_for_server_to_purge_messages(marie, pauline) + assert_equals(CoreManager.call(marie, pauline), True) + msg = chat_room.create_message("Bla bla bla bla") + chat_room.send_message2(msg, None, None) + assert_equals(CoreManager.wait_for(pauline, marie, lambda pauline, marie: marie.stats.number_of_LinphoneMessageReceived == 1), True) + assert marie.lc.get_chat_room(pauline.identity) is not None + marie.stop() + pauline.stop() diff --git a/tools/python/unittests/test_presence.py b/tools/python/unittests/test_presence.py new file mode 100644 index 000000000..3de4e2e2a --- /dev/null +++ b/tools/python/unittests/test_presence.py @@ -0,0 +1,44 @@ +from nose.tools import assert_equals +from copy import deepcopy +import linphone +from linphonetester import * +import os +import time + + +class PresenceCoreManager(CoreManager): + + def __init__(self, username, logger = None): + CoreManager.__init__(self, 'empty_rc', False, logger=logger) + self.identity = self.lc.primary_contact_parsed + self.identity.username = username + self.lc.primary_contact = self.identity.as_string() + +class TestPresence: + + @classmethod + def setup_class(cls): + base, ext = os.path.splitext(os.path.basename(__file__)) + cls.logger = Logger(base + '.log') + + def subscribe_to_callee_presence(self, caller_mgr, callee_mgr): + initial_caller_stats = deepcopy(caller_mgr.stats) + initial_callee_stats = deepcopy(callee_mgr.stats) + identity = callee_mgr.identity.as_string_uri_only() + friend = caller_mgr.lc.create_friend_with_address(identity) + friend.edit() + friend.subscribes_enabled = True + friend.done() + caller_mgr.lc.add_friend(friend) + result = CoreManager.wait_for(caller_mgr, callee_mgr, + lambda caller_mgr, callee_mgr: caller_mgr.stats.number_of_LinphonePresenceActivityOnline == initial_caller_stats.number_of_LinphonePresenceActivityOnline + 1) + assert_equals(callee_mgr.stats.number_of_NewSubscriptionRequest, initial_callee_stats.number_of_NewSubscriptionRequest + 1) + assert_equals(caller_mgr.stats.number_of_NotifyReceived, initial_caller_stats.number_of_NotifyReceived + 1) + return result + + def test_simple_subscribe(self): + marie = PresenceCoreManager('marie', logger=TestPresence.logger) + pauline = PresenceCoreManager('pauline', logger=TestPresence.logger) + assert_equals(self.subscribe_to_callee_presence(marie, pauline), True) + marie.stop() + pauline.stop() diff --git a/tools/python/unittests/test_register.py b/tools/python/unittests/test_register.py new file mode 100644 index 000000000..2660fbf1c --- /dev/null +++ b/tools/python/unittests/test_register.py @@ -0,0 +1,87 @@ +from nose.tools import assert_equals +import linphone +from linphonetester import * +import os +import time + +class RegisterCoreManager(CoreManager): + + @classmethod + def auth_info_requested(cls, lc, realm, username, domain): + CoreManager.auth_info_requested(cls, lc, realm, username, domain) + info = linphone.AuthInfo.new(test_username, None, test_password, None, realm, domain) # Create authentication structure from identity + lc.add_auth_info(info) # Add authentication info to LinphoneCore + + def __init__(self, with_auth = False, logger = None): + vtable = {} + if with_auth: + vtable['auth_info_requested'] = RegisterCoreManager.auth_info_requested + CoreManager.__init__(self, vtable=vtable, logger=logger) + + def register_with_refresh(self, refresh, domain, route, late_auth_info = False, expected_final_state = linphone.RegistrationState.RegistrationOk): + assert self.lc is not None + self.stats.reset() + proxy_cfg = self.lc.create_proxy_config() + from_address = create_address(domain) + proxy_cfg.identity = from_address.as_string() + server_addr = from_address.domain + proxy_cfg.register_enabled = True + proxy_cfg.expires = 1 + if route is None: + proxy_cfg.server_addr = server_addr + else: + proxy_cfg.route = route + proxy_cfg.server_addr = route + self.lc.add_proxy_config(proxy_cfg) + self.lc.default_proxy_config = proxy_cfg + + #linphone_core_set_sip_transports(lc,&transport); + + retry = 0 + expected_count = 1 + if refresh: + expected_count += 1 + max_retry = 110 + if expected_final_state == linphone.RegistrationState.RegistrationProgress: + max_retry += 200 + while self.stats.number_of_LinphoneRegistrationOk < expected_count and retry < max_retry: + retry += 1 + self.lc.iterate() + if self.stats.number_of_auth_info_requested > 0 and proxy_cfg.state == linphone.RegistrationState.RegistrationFailed and late_auth_info: + if len(self.lc.auth_info_list) == 0: + assert_equals(proxy_cfg.error, linphone.Reason.ReasonUnauthorized) + info = linphone.AuthInfo.new(test_username, None, test_password, None, None, None) # Create authentication structure from identity + self.lc.add_auth_info(info) + if proxy_cfg.error == linphone.Reason.ReasonForbidden or \ + (self.stats.number_of_auth_info_requested > 2 and proxy_cfg.error == linphone.Reason.ReasonUnauthorized): + break + time.sleep(0.1) + + assert_equals(proxy_cfg.state, expected_final_state) + assert_equals(self.stats.number_of_LinphoneRegistrationNone, 0) + assert self.stats.number_of_LinphoneRegistrationProgress >= 1 + if expected_final_state == linphone.RegistrationState.RegistrationOk: + assert_equals(self.stats.number_of_LinphoneRegistrationOk, expected_count) + expected_failed = 0 + if late_auth_info: + expected_failed = 1 + assert_equals(self.stats.number_of_LinphoneRegistrationFailed, expected_failed) + else: + assert_equals(self.stats.number_of_LinphoneRegistrationCleared, 0) + + self.stop() + # Not testable as the callbacks can not be called once the core destruction has started + #assert_equals(self.stats.number_of_LinphoneRegistrationCleared, 1) + + +class TestRegister: + + @classmethod + def setup_class(cls): + base, ext = os.path.splitext(os.path.basename(__file__)) + cls.logger = Logger(base + '.log') + + def test_simple_register(self): + cm = RegisterCoreManager(logger=TestRegister.logger) + cm.register_with_refresh(False, None, None) + assert_equals(cm.stats.number_of_auth_info_requested, 0) diff --git a/tools/python/unittests/test_setup.py b/tools/python/unittests/test_setup.py new file mode 100644 index 000000000..ff710217f --- /dev/null +++ b/tools/python/unittests/test_setup.py @@ -0,0 +1,44 @@ +from nose.tools import assert_equals +import linphone +from linphonetester import * +import os + +class TestSetup: + + @classmethod + def setup_class(cls): + base, ext = os.path.splitext(os.path.basename(__file__)) + cls.logger = Logger(base + '.log') + + def test_address(self): + create_address(None) + + def test_core_init(self): + lc = linphone.Core.new({}, None, None) + assert lc is not None + if lc is not None: + lc.verify_server_certificates(False) + + def test_interpret_url(self): + lc = linphone.Core.new({}, None, None) + assert lc is not None + sips_address = "sips:margaux@sip.linphone.org" + address = lc.interpret_url(sips_address) + assert address is not None + assert_equals(address.scheme, "sips") + assert_equals(address.username, "margaux") + assert_equals(address.domain, "sip.linphone.org") + + def test_lpconfig_from_buffer(self): + buffer = "[buffer]\ntest=ok" + buffer_linebreaks = "[buffer_linebreaks]\n\n\n\r\n\n\r\ntest=ok" + conf = linphone.LpConfig.new_from_buffer(buffer) + assert_equals(conf.get_string("buffer", "test", ""), "ok") + conf = linphone.LpConfig.new_from_buffer(buffer_linebreaks) + assert_equals(conf.get_string("buffer_linebreaks", "test", ""), "ok") + + def test_create_chat_room(self): + lc = linphone.Core.new({}, None, None) + assert lc is not None + cr = lc.get_chat_room_from_uri("sip:toto@titi.com") + assert cr is not None diff --git a/tools/xml2lpc_test.c b/tools/xml2lpc_test.c index e99b90bd8..3bb5dbc31 100644 --- a/tools/xml2lpc_test.c +++ b/tools/xml2lpc_test.c @@ -43,17 +43,18 @@ void cb_function(void *ctx, xml2lpc_log_level level, const char *msg, va_list li void show_usage(int argc, char *argv[]) { fprintf(stderr, "usage %s convert \n" - " %s validate \n", + " %s validate \n", argv[0], argv[0]); } int main(int argc, char *argv[]) { + xml2lpc_context *ctx; if(argc != 4) { show_usage(argc, argv); return -1; } - - xml2lpc_context *ctx = xml2lpc_context_new(cb_function, NULL); + + ctx = xml2lpc_context_new(cb_function, NULL); xml2lpc_set_xml_file(ctx, argv[2]); if(strcmp("convert", argv[1]) == 0) { LpConfig *lpc = lp_config_new(argv[3]);